aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
-rw-r--r--src/jogl/classes/jogamp/opengl/Debug.java51
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLibraryBundleInfo.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java15
-rw-r--r--src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java116
-rw-r--r--src/jogl/classes/jogamp/opengl/FPSCounterImpl.java62
-rw-r--r--src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java739
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java520
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferSizeTracker.java193
-rw-r--r--src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java207
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java1872
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextShareSet.java214
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java172
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java481
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableHelper.java1195
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableImpl.java304
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLibraryBundleInfo.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDynamicLookupHelper.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java593
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java268
-rw-r--r--src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java140
-rw-r--r--src/jogl/classes/jogamp/opengl/GLPbufferImpl.java298
-rw-r--r--src/jogl/classes/jogamp/opengl/GLRunnableTask.java48
-rw-r--r--src/jogl/classes/jogamp/opengl/GLStateTracker.java75
-rw-r--r--src/jogl/classes/jogamp/opengl/GLVersionNumber.java153
-rw-r--r--src/jogl/classes/jogamp/opengl/GLWorkerThread.java29
-rw-r--r--src/jogl/classes/jogamp/opengl/GLXExtensions.java37
-rw-r--r--src/jogl/classes/jogamp/opengl/ListenerSyncedImplStub.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/MemoryObject.java65
-rw-r--r--src/jogl/classes/jogamp/opengl/ProjectFloat.java452
-rw-r--r--src/jogl/classes/jogamp/opengl/SharedResourceRunner.java220
-rw-r--r--src/jogl/classes/jogamp/opengl/ThreadingImpl.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/ToolkitThreadingPlugin.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java428
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTThreadingPlugin.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java400
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/AWTUtil.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/Java2D.java271
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/awt/VersionApplet.java15
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java47
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLContext.java254
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java337
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java262
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java833
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java60
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLDynamicLibraryBundleInfo.java55
-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.java50
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java59
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java459
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java287
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java59
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java62
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java217
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/gl2/ProjectDouble.java92
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java150
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/Glue.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/error/Error.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java38
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java198
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1010102.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract1555rev.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract2101010rev.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract233rev.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract332.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract4444rev.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract5551.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract565rev.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Extract8888rev.java26
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractFloat.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractPrimitive.java8
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSByte.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSInt.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java16
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java276
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java120
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Mipmap.java200
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/PixelStorageModes.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/ScaleInternal.java441
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/mipmap/Type_Widget.java80
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Breakpt.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfArcs.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfQuiltspecs.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Knotvector.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java12
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/nurbs/TrimVertex.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/registry/Registry.java14
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java1239
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java96
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java316
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java247
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java57
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java17
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java104
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java21
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java91
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java117
-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.java21
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java121
-rw-r--r--src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java947
-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.java61
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLDataArrayHandler.java52
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandler.java58
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/util/GLVBOArrayHandler.java71
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java77
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java1598
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java229
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java129
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/NullGLMediaPlayer.java137
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java439
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java1029
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java281
-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.java130
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java100
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java70
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerInterleaved.java66
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java195
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java271
-rw-r--r--src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java1224
-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.java1517
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/FilterType.java67
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/FilterWriteStrategy.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageInfo.java56
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ImageLine.java372
-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/PngHelperInternal.java (renamed from src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java)147
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkInputStream.java72
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngReader.java1416
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngWriter.java709
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjExceptionInternal.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/PngjUnsupportedException.java3
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java15
-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.java107
-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.java250
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java50
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java58
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java30
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java35
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java29
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java20
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIHDR.java41
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java36
-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.java30
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPLTE.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSBIT.java42
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java55
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSRGB.java28
-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.java32
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTIME.java40
-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.java10
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java21
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java28
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java214
-rw-r--r--src/jogl/classes/jogamp/opengl/util/pngj/package.html5
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java121
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java23
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java110
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java105
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java48
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java34
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java53
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java22
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java150
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java167
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java218
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java80
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java387
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java18
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java687
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java307
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java31
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/GLXUtil.java109
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java93
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java78
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java50
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java7
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java359
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java379
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java33
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java495
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java303
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java48
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java54
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java64
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java100
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java70
-rw-r--r--src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java45
268 files changed, 26849 insertions, 12203 deletions
diff --git a/src/jogl/classes/jogamp/opengl/Debug.java b/src/jogl/classes/jogamp/opengl/Debug.java
index 4287c1960..9332b670a 100644
--- a/src/jogl/classes/jogamp/opengl/Debug.java
+++ b/src/jogl/classes/jogamp/opengl/Debug.java
@@ -1,21 +1,22 @@
/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- *
+ * 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
@@ -28,17 +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.
- *
+ *
* 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.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -47,9 +51,15 @@ 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) {
@@ -60,27 +70,18 @@ public class Debug extends PropertyAccess {
}
}
- 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(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..578f416b7 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(String funcName) {
return true;
}
-
+
}
diff --git a/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java b/src/jogl/classes/jogamp/opengl/DesktopGLDynamicLookupHelper.java
index ff49303ca..c1e1d1821 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;
@@ -37,9 +37,10 @@ public class DesktopGLDynamicLookupHelper extends GLDynamicLookupHelper {
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>();
diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
index 610f08e21..fd59ecfd4 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,25 @@
* 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.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 +62,7 @@ final class ExtensionAvailabilityCache {
}
/**
- * Flush the cache.
+ * Flush the cache.
*/
final void flush()
{
@@ -78,24 +83,24 @@ final class ExtensionAvailabilityCache {
}
final boolean isInitialized() {
- return initialized && !availableExtensionCache.isEmpty() ;
+ return initialized;
}
final int getTotalExtensionCount() {
validateInitialization();
return availableExtensionCache.size();
}
-
+
final boolean isExtensionAvailable(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 +110,7 @@ final class ExtensionAvailabilityCache {
validateInitialization();
return glExtensionCount;
}
-
+
final String getGLExtensionsString() {
validateInitialization();
if(DEBUG) {
@@ -149,7 +154,6 @@ 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 int count;
@@ -160,78 +164,84 @@ final class ExtensionAvailabilityCache {
}
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();
+ int major[] = new int[] { version.getMajor() };
+ 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 +255,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..08a1fe882 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 = ( (float)fpsUpdateFramesInterval * 1000f ) / ( (float) fpsLastPeriod ) ;
+
fpsTotalDuration = now - fpsStartTime;
fpsTotalDuration = Math.max(fpsTotalDuration, 1); // div 0
fpsTotal= ( (float)fpsTotalFrames * 1000f ) / ( (float) 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();
}
-
+
+ @Override
public final synchronized void setUpdateFPSFrames(int frames, 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
new file mode 100644
index 000000000..7cd685d5a
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -0,0 +1,739 @@
+/**
+ * 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;
+
+import java.io.PrintStream;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.opengl.FPSCounter;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+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.GLOffscreenAutoDrawable;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.GLSharedContextSetter;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLEventListenerState;
+import com.jogamp.opengl.GLStateKeeper;
+
+
+/**
+ * Abstract common code for GLAutoDrawable implementations.
+ *
+ * @see GLAutoDrawable
+ * @see GLAutoDrawableDelegate
+ * @see GLOffscreenAutoDrawable
+ * @see GLOffscreenAutoDrawableImpl
+ * @see GLPBufferImpl
+ * @see com.jogamp.newt.opengl.GLWindow
+ */
+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 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
+
+ /**
+ * <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) {
+ this.drawable = drawable;
+ this.context = context;
+ this.preserveGLELSAtDestroy = false;
+ this.glels = null;
+ this.glStateKeeperListener = null;
+ this.ownsDevice = ownsDevice;
+ if(null != context && null != drawable) {
+ context.setGLDrawable(drawable, false);
+ }
+ resetFPSCounter();
+ }
+
+ @Override
+ public final void setSharedContext(GLContext sharedContext) throws IllegalStateException {
+ helper.setSharedContext(this.context, sharedContext);
+ }
+
+ @Override
+ public final void setSharedAutoDrawable(GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
+ helper.setSharedAutoDrawable(this, sharedAutoDrawable);
+ }
+
+ /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access on top of {@link NativeSurface#lockSurface()}. */
+ protected abstract RecursiveLock getLock();
+
+ @Override
+ public final GLStateKeeper.Listener setGLStateKeeperListener(Listener l) {
+ final GLStateKeeper.Listener pre = glStateKeeperListener;
+ glStateKeeperListener = l;
+ return pre;
+ }
+
+ @Override
+ public final boolean preserveGLStateAtDestroy(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;
+ }
+
+ /** 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.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 {
+ GLDrawableImpl _drawable = drawable;
+ if( null!=_drawable ) {
+ if(DEBUG) {
+ 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();
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ if( _drawable.isRealized() ) {
+ 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}
+ * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default),
+ * a thread safe destruction is being induced.
+ * </p>
+ */
+ protected final void defaultWindowDestroyNotifyOp() {
+ final NativeSurface ns = getNativeSurface();
+ final boolean shallClose;
+ if(ns instanceof WindowClosingProtocol) {
+ shallClose = WindowClosingMode.DISPOSE_ON_CLOSE == ((WindowClosingProtocol)ns).getDefaultCloseOperation();
+ } else {
+ shallClose = true;
+ }
+ if( shallClose ) {
+ destroyAvoidAwareOfLocking();
+ }
+ }
+
+ /**
+ * 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.
+ * 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
+ * call of display().
+ * </p>
+ * <p>
+ * This method is being used to avoid deadlock if
+ * destruction is desired by <i>other</i> threads, e.g. the window manager.
+ * </p>
+ * @see #defaultWindowDestroyNotifyOp()
+ * @see #defaultDisplay()
+ */
+ protected final void destroyAvoidAwareOfLocking() {
+ final NativeSurface ns = getNativeSurface();
+
+ final GLAnimatorControl ctrl = helper.getAnimator();
+
+ // Is an animator thread perform rendering?
+ if ( helper.isAnimatorStartedOnOtherThread() ) {
+ // Pause animations before initiating safe destroy.
+ final boolean isPaused = ctrl.pause();
+ destroy();
+ if(isPaused) {
+ ctrl.resume();
+ }
+ } else if (null != ns && ns.isSurfaceLockedByOtherThread()) {
+ // Surface is locked by another thread.
+ // Flag that destroy should be performed on the next
+ // attempt to display.
+ sendDestroy = true; // async, but avoiding deadlock
+ } else {
+ // Without an external thread animating or locking the
+ // surface, we are safe.
+ destroy();
+ }
+ }
+
+ /**
+ * Calls {@link #destroyImplInLock()} while claiming the lock.
+ */
+ protected final void defaultDestroy() {
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ destroyImplInLock();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Default implementation to destroys the drawable and context of this GLAutoDrawable:
+ * <ul>
+ * <li>issues the GLEventListener dispose call, if drawable and context are valid</li>
+ * <li>destroys the GLContext, if valid</li>
+ * <li>destroys the GLDrawable, if valid</li>
+ * </ul>
+ * <p>Method assumes the lock is being hold.</p>
+ * <p>Override it to extend it to destroy your resources, i.e. the actual window.
+ * In such case call <code>super.destroyImplInLock</code> first.</p>
+ */
+ protected void destroyImplInLock() {
+ if( preserveGLELSAtDestroy ) {
+ preserveGLStateAtDestroy(false);
+ preserveGLEventListenerState();
+ }
+ if( null != context ) {
+ if( context.isCreated() ) {
+ // Catch dispose GLExceptions by GLEventListener, just 'print' them
+ // so we can continue with the destruction.
+ try {
+ helper.disposeGL(this, context, true);
+ } catch (GLException gle) {
+ gle.printStackTrace();
+ }
+ }
+ context = null;
+ }
+ if( null != drawable ) {
+ final AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
+ drawable.setRealized(false);
+ drawable = null;
+ if( ownsDevice ) {
+ device.close();
+ }
+ }
+ }
+
+ public final void defaultSwapBuffers() throws GLException {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if(null != drawable) {
+ drawable.swapBuffers();
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ //
+ // GLAutoDrawable
+ //
+
+ protected final Runnable defaultInitAction = new Runnable() {
+ @Override
+ public final void run() {
+ // Lock: Locked Surface/Window by MakeCurrent/Release
+ helper.init(GLAutoDrawableBase.this, !sendReshape);
+ resetFPSCounter();
+ } };
+
+ protected final Runnable defaultDisplayAction = new Runnable() {
+ @Override
+ public final void run() {
+ // Lock: Locked Surface/Window by display _and_ MakeCurrent/Release
+ if (sendReshape) {
+ helper.reshape(GLAutoDrawableBase.this, 0, 0, getWidth(), getHeight());
+ sendReshape = false;
+ }
+ helper.display(GLAutoDrawableBase.this);
+ fpsCounter.tickFPS();
+ } };
+
+ protected final void defaultDisplay() {
+ if( sendDestroy ) {
+ sendDestroy=false;
+ destroy();
+ return;
+ }
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ if( null == context ) {
+ boolean contextCreated = false;
+ final GLDrawableImpl _drawable = drawable;
+ if ( null != _drawable && _drawable.isRealized() && 0<_drawable.getWidth()*_drawable.getHeight() ) {
+ 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);
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
+ protected final GLEventListener defaultDisposeGLEventListener(GLEventListener listener, boolean remove) {
+ final RecursiveLock _lock = getLock();
+ _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, boolean destroyPrevCtx) {
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ final GLContext oldCtx = context;
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
+ context=(GLContextImpl)newCtx;
+ return oldCtx;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public final GL getGL() {
+ final GLContext _context = context;
+ if (_context == null) {
+ return null;
+ }
+ return _context.getGL();
+ }
+
+ @Override
+ public final GL setGL(GL gl) {
+ final GLContext _context = context;
+ if (_context != null) {
+ _context.setGL(gl);
+ return gl;
+ }
+ return null;
+ }
+
+ @Override
+ public final void addGLEventListener(GLEventListener listener) {
+ helper.addGLEventListener(listener);
+ }
+
+ @Override
+ public final void addGLEventListener(int index, GLEventListener listener) throws IndexOutOfBoundsException {
+ helper.addGLEventListener(index, listener);
+ }
+
+ @Override
+ public int getGLEventListenerCount() {
+ return helper.getGLEventListenerCount();
+ }
+
+ @Override
+ public GLEventListener getGLEventListener(int index) throws IndexOutOfBoundsException {
+ return helper.getGLEventListener(index);
+ }
+
+ @Override
+ public boolean areAllGLEventListenerInitialized() {
+ return helper.areAllGLEventListenerInitialized();
+ }
+
+ @Override
+ public boolean getGLEventListenerInitState(GLEventListener listener) {
+ return helper.getGLEventListenerInitState(listener);
+ }
+
+ @Override
+ public void setGLEventListenerInitState(GLEventListener listener, boolean initialized) {
+ helper.setGLEventListenerInitState(listener, initialized);
+ }
+
+ @Override
+ public GLEventListener disposeGLEventListener(GLEventListener listener, boolean remove) {
+ return defaultDisposeGLEventListener(listener, remove);
+ }
+
+ @Override
+ public final GLEventListener removeGLEventListener(GLEventListener listener) {
+ return helper.removeGLEventListener(listener);
+ }
+
+ @Override
+ public final void setAnimator(GLAnimatorControl animatorControl)
+ throws GLException {
+ helper.setAnimator(animatorControl);
+ }
+
+ @Override
+ public final GLAnimatorControl getAnimator() {
+ return helper.getAnimator();
+ }
+
+ @Override
+ public final Thread setExclusiveContextThread(Thread t) throws GLException {
+ return helper.setExclusiveContextThread(t, context);
+ }
+
+ @Override
+ public final Thread getExclusiveContextThread() {
+ return helper.getExclusiveContextThread();
+ }
+
+ @Override
+ public final boolean invoke(boolean wait, GLRunnable glRunnable) {
+ return helper.invoke(this, wait, glRunnable);
+ }
+
+ @Override
+ public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) {
+ return helper.invoke(this, wait, glRunnables);
+ }
+
+ @Override
+ public final void setAutoSwapBufferMode(boolean enable) {
+ helper.setAutoSwapBufferMode(enable);
+ }
+
+ @Override
+ public final boolean getAutoSwapBufferMode() {
+ return helper.getAutoSwapBufferMode();
+ }
+
+ @Override
+ public final void setContextCreationFlags(int flags) {
+ additionalCtxCreationFlags = flags;
+ final GLContext _context = context;
+ if(null != _context) {
+ _context.setContextCreationFlags(additionalCtxCreationFlags);
+ }
+ }
+
+ @Override
+ public final int getContextCreationFlags() {
+ return additionalCtxCreationFlags;
+ }
+
+ //
+ // FPSCounter
+ //
+
+ @Override
+ public final void setUpdateFPSFrames(int frames, 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();
+ }
+
+ //
+ // GLDrawable delegation
+ //
+
+ @Override
+ public final GLContext createContext(final GLContext shareWith) {
+ final RecursiveLock lock = getLock();
+ lock.lock();
+ try {
+ if(drawable != null) {
+ final GLContext _ctx = drawable.createContext(shareWith);
+ _ctx.setContextCreationFlags(additionalCtxCreationFlags);
+ return _ctx;
+ }
+ return null;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ @Override
+ public final void setRealized(boolean realized) {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized && ( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) ) {
+ 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() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getWidth() : 0;
+ }
+
+ @Override
+ public int getHeight() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getHeight() : 0;
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
+ @Override
+ public final GLCapabilitiesImmutable getChosenGLCapabilities() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getChosenGLCapabilities() : null;
+ }
+
+ @Override
+ public final GLProfile getGLProfile() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getGLProfile() : null;
+ }
+
+ @Override
+ public final NativeSurface getNativeSurface() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.getNativeSurface() : null;
+ }
+
+ @Override
+ public final long getHandle() {
+ 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 +
+ ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]";
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
new file mode 100644
index 000000000..472bfbd58
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLBufferObjectTracker.java
@@ -0,0 +1,520 @@
+/**
+ * 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;
+
+/**
+ * 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 = Debug.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);
+ }
+ final void setMappedBuffer(final ByteBuffer bb) {
+ if (DEBUG) {
+ System.err.printf("%s.GLBufferStorage.setMappedBuffer: %s: %s -> %s%n", msgClazzName, toString(true), mappedBuffer, bb);
+ }
+ mappedBuffer = bb;
+ }
+ }
+
+ /**
+ * 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, int mutableUsage, 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 objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, immutableFlags);
+ final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, objNew);
+ if (DEBUG) {
+ System.err.printf("%s.%s target: 0x%X -> %d: %s -> %s%n", msgClazzName, msgCreateBound, target, bufferName, objOld, objNew);
+ }
+ if( null != objOld ) {
+ objOld.setMappedBuffer(null);
+ }
+ }
+
+ /**
+ * 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, 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 objNew = new GLBufferStorageImpl(bufferName, size, mutableUsage, 0 /* immutableFlags */);
+ final GLBufferStorageImpl objOld = (GLBufferStorageImpl) bufferName2StorageMap.put(bufferName, objNew);
+ if (DEBUG) {
+ System.err.printf("%s.%s direct: %d: %s -> %s%n", msgClazzName, msgCreateNamed, bufferName, objOld, objNew);
+ }
+ if( null != objOld ) {
+ objOld.setMappedBuffer(null);
+ }
+ }
+
+ /**
+ * 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 */, length, access, 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 */, false /* useRange */, 0 /* offset */, 0 /* 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,
+ long offset, 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 long getBufferSize(final int bufferName) {
+ final GLBufferStorageImpl store = (GLBufferStorageImpl)bufferName2StorageMap.get(bufferName);
+ if ( null == store ) {
+ if (DEBUG) {
+ System.err.printf("%s: %s.getBufferSize(): Buffer %d not tracked%n", warning, msgClazzName, bufferName);
+ Thread.dumpStack();
+ }
+ return 0;
+ }
+ return store.getSize();
+ }
+
+ 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..511c1b9b9 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,6 +41,7 @@
package jogamp.opengl;
import javax.media.opengl.*;
+
import com.jogamp.common.util.IntIntHashMap;
/**
@@ -49,8 +50,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 +66,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 = Debug.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 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);
}
- 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 GL2.GL_PIXEL_PACK_BUFFER: return GL2.GL_PIXEL_PACK_BUFFER_BINDING;
+ case GL2.GL_PIXEL_UNPACK_BUFFER: return GL2.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 GL2.GL_PIXEL_PACK_BUFFER:
+ case GL2.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(int target, 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();
}
}
@@ -114,27 +217,24 @@ public class GLBufferStateTracker {
return value is valid. */
public final int getBoundBufferObject(int target, 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 +242,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 +256,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(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 51201b3a9..9ccd78589 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.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,39 +29,51 @@
* 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.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.gluegen.runtime.FunctionAddressResolver;
+import com.jogamp.common.util.VersionNumber;
+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.GLExtensionNames;
+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.GL3;
+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;
@@ -74,7 +86,7 @@ public abstract class GLContextImpl extends GLContext {
private String contextFQN;
private int additionalCtxCreationFlags;
-
+
// Cache of the functions that are available to be called at the current
// moment in time
protected ExtensionAvailabilityCache extensionAvailability;
@@ -82,19 +94,26 @@ public abstract class GLContextImpl extends GLContext {
// OpenGL functions.
private ProcAddressTable glProcAddressTable;
+ private String glVendor;
private String glRenderer;
private String glRendererLowerCase;
-
- // Tracks creation and initialization of buffer objects to avoid
+ private String glVersion;
+
+ // Tracks lifecycle of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
- private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
- private GLStateTracker glStateTracker = new GLStateTracker();
+ 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;
+
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
+ private volatile boolean pixelDataEvaluated;
+ private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -112,72 +131,128 @@ public abstract class GLContextImpl extends GLContext {
public static void shutdownImpl() {
mappedExtensionAvailabilityCache.clear();
mappedGLProcAddress.clear();
- mappedGLXProcAddress.clear();
+ mappedGLXProcAddress.clear();
}
-
+
public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) {
super();
- if (shareWith != null) {
+ bufferStateTracker = new GLBufferStateTracker();
+ if ( null != shareWith ) {
GLContextShareSet.registerSharing(this, shareWith);
+ bufferObjectTracker = ((GLContextImpl)shareWith).getBufferObjectTracker();
+ assert (bufferObjectTracker != null) : "shared context hash null GLBufferObjectTracker: "+shareWith;
+ } else {
+ bufferObjectTracker = new GLBufferObjectTracker();
}
- GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this);
this.drawable = drawable;
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) {
- bufferStateTracker.clearBufferObjectState();
+ private final void clearStates() {
+ if( !GLContextShareSet.hasCreatedSharedLeft(this) ) {
+ bufferObjectTracker.clear();
}
+ bufferStateTracker.clear();
+ glStateTracker.setEnabled(false);
+ glStateTracker.clearStates();
+ }
- if (glStateTracker != null) {
- glStateTracker.clearStates(false);
+ @Override
+ protected void resetStates(boolean isInit) {
+ if( !isInit ) {
+ clearStates();
}
-
extensionAvailability = null;
glProcAddressTable = null;
gl = null;
contextFQN = null;
additionalCtxCreationFlags = 0;
- glRenderer = "";
+ glVendor = "";
+ glRenderer = glVendor;
glRendererLowerCase = glRenderer;
-
- super.resetStates();
+ glVersion = glVendor;
+
+ if (boundFBOTarget != null) { // <init>
+ boundFBOTarget[0] = 0; // draw
+ boundFBOTarget[1] = 0; // read
+ }
+
+ pixelDataEvaluated = false;
+
+ super.resetStates(isInit);
}
- public final void setGLReadDrawable(GLDrawable read) {
- if(null!=read && drawable!=read && !isGLReadDrawableAvailable()) {
- throw new GLException("GL Read Drawable not available");
+ @Override
+ public final GLDrawable setGLReadDrawable(GLDrawable read) {
+ if(!isGLReadDrawableAvailable()) {
+ throw new GLException("Setting read drawable feature not available");
}
- boolean lockHeld = lock.isOwner();
+ 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;
}
+ @Override
public final GLDrawable getGLReadDrawable() {
return drawableRead;
}
+ @Override
+ public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
+ }
+ 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(..)");
+ }
+ final GLDrawableImpl old = drawable;
+ if( isCreated() && null != old && old.isRealized() ) {
+ if(!lockHeld) {
+ makeCurrent();
+ }
+ associateDrawable(false);
+ if(!lockHeld) {
+ release();
+ }
+ }
+ if(lockHeld) {
+ release();
+ }
+ 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();
+ }
+ }
+ return old;
+ }
+
+ @Override
public final GLDrawable getGLDrawable() {
return drawable;
}
@@ -186,30 +261,48 @@ public abstract class GLContextImpl extends GLContext {
return (GLDrawableImpl) getGLDrawable();
}
+ @Override
+ public final GL getRootGL() {
+ GL _gl = gl;
+ GL _parent = _gl.getDownstreamGL();
+ while ( null != _parent ) {
+ _gl = _parent;
+ _parent = _gl.getDownstreamGL();
+ }
+ return _gl;
+ }
+
+ @Override
public final GL getGL() {
return gl;
}
+ @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();
+ 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).
- *
+ *
* <p>
- * This is currently being used and overridden by Mac OSX,
+ * This is currently being used and overridden by Mac OSX,
* which issues the {@link jogamp.opengl.macosx.cgl.CGL#updateContext(long) NSOpenGLContext update()} call.
* </p>
- *
+ *
* @throws GLException
*/
protected void drawableUpdatedNotify() throws GLException { }
@@ -217,22 +310,40 @@ public abstract class GLContextImpl extends GLContext {
public abstract Object getPlatformGLExtensions();
// Note: the surface is locked within [makeCurrent .. swap .. release]
+ @Override
public void release() throws GLException {
release(false);
}
- private void release(boolean force) throws GLException {
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: - release() - force: "+force+", "+lock);
+ private void release(boolean inDestruction) throws GLException {
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock);
}
- if ( !lock.isOwner() ) {
- throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this);
+ if ( !lock.isOwner(Thread.currentThread()) ) {
+ final String msg = getThreadName() +": Context not current on thread, obj " + toHexString(hashCode())+", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock;
+ 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);
}
- final boolean actualRelease = force || lock.getHoldCount() == 1 ;
- try {
+
+ Throwable drawableContextMadeCurrentException = null;
+ final boolean actualRelease = ( inDestruction || lock.getHoldCount() == 1 ) && 0 != contextHandle;
+ try {
if( actualRelease ) {
- if (contextHandle != 0) { // allow dbl-release
- releaseImpl();
+ if( !inDestruction ) {
+ try {
+ contextMadeCurrent(false);
+ } catch (Throwable t) {
+ drawableContextMadeCurrentException = t;
+ }
}
+ releaseImpl();
}
} finally {
// exception prone ..
@@ -241,68 +352,106 @@ public abstract class GLContextImpl extends GLContext {
}
drawable.unlockSurface();
lock.unlock();
- if(TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: - "+(actualRelease?"switch":"keep ")+" - CONTEXT_RELEASE - "+lock);
+ if( DEBUG_TRACE_SWITCH ) {
+ final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep ")+" - "+lock;
+ 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);
+ }
+
}
+ 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: " + toHexString(contextHandle) +
- ", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ if ( DEBUG_TRACE_SWITCH ) {
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
+ System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
+ ", surf "+toHexString(drawH)+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
- 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 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.
- // FIXME: This is actually impossible now, since we acquired the surface lock already,
- // which is a prerequisite to acquire the context lock.
- lock.lock(); // holdCount++ -> 1 or 2
+ lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
if ( lock.getHoldCount() > 2 ) {
- throw new GLException(getThreadName() + ": Lock was hold more than once - makeCurrent/release imbalance: "+lock);
+ 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);
+ Thread.dumpStack();
+ }
}
- try {
- // release current context
- if(null != glDebugHandler) {
- if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
- makeCurrent();
+ try {
+ // 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());
}
- glDebugHandler.enable(false);
}
+ try {
+ associateDrawable(false);
+ } catch (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) {
// pending release() after makeCurrent()
- release(true);
+ release(true);
}
destroyImpl();
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: " + toHexString(contextHandle) +
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
}
} finally {
drawable.unlockSurface();
}
+ 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 {
if (source.getHandle() == 0) {
throw new GLException("Source OpenGL context has not been created");
@@ -311,8 +460,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");
}
@@ -364,98 +513,110 @@ public abstract class GLContextImpl extends GLContext {
* @see #mapVersionAvailable
* @see #destroyContextARBImpl
*/
- public int makeCurrent() throws GLException {
- boolean unlockContextAndDrawable = false;
- int res = CONTEXT_NOT_CURRENT;
+ @Override
+ public final int makeCurrent() throws GLException {
+ return makeCurrent(false);
+ }
+
+ protected final int makeCurrent(boolean forceDrawableAssociation) throws GLException {
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+lock);
+ }
// 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]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - Surface Not Ready - CONTEXT_NOT_CURRENT - "+lock);
+ }
return CONTEXT_NOT_CURRENT;
}
+
+ boolean unlockResources = true; // Must be cleared if successful, otherwise finally block will release context and/or surface!
+ int res = 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: - keep - CONTEXT_CURRENT - "+lock);
- }
- return CONTEXT_CURRENT;
- } else {
- current.release();
- }
- }
- if (0 == drawable.getHandle()) {
+ 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]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock);
+ }
+ return CONTEXT_CURRENT;
+ } else {
+ current.release();
+ }
}
- */
- } catch (RuntimeException e) {
- unlockContextAndDrawable = true;
- throw e;
- } finally {
- if (unlockContextAndDrawable) {
- lock.unlock();
- }
- }
+ 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 (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 (RuntimeException e) {
- unlockContextAndDrawable = true;
+ 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: - switch - CONTEXT_NOT_CURRENT - "+lock);
}
- } else {
+ }
+
+ if (res != CONTEXT_NOT_CURRENT) {
setCurrent(this);
if(res == CONTEXT_CURRENT_NEW) {
// check if the drawable's and the GL's GLProfile are equal
- // throws an GLException if not
+ // throws an GLException if not
getGLDrawable().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 } ) );
- }
- if(DEBUG || TRACE_SWITCH) {
- System.err.println(getThreadName() +": GLContext.ContextSwitch: - 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: - 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
@@ -465,68 +626,94 @@ public abstract class GLContextImpl extends GLContext {
}
*/
}
+ if( TRACE_SWITCH ) {
+ System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X3]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - "+makeCurrentResultToString(res)+" - stateTracker.on "+glStateTracker.isEnabled()+" - "+lock);
+ }
return res;
}
private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
if (!isCreated()) {
+ if( 0 >= drawable.getWidth() || 0 >= drawable.getHeight() ) {
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": Create GL context REJECTED (zero surface size) obj " + toHexString(hashCode()) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName());
+ 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);
+
+ final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getCreatedShare(this);
+ final long shareWithHandle;
if (null != shareWith) {
shareWith.getDrawableImpl().lockSurface();
+ shareWithHandle = shareWith.getHandle();
+ if (0 == shareWithHandle) {
+ throw new GLException("GLContextShareSet returned an invalid OpenGL context: "+this);
+ }
+ } else {
+ shareWithHandle = 0;
}
final boolean created;
try {
- created = createImpl(shareWith); // may throws exception if fails!
+ created = createImpl(shareWithHandle); // 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 != shareWith) {
shareWith.getDrawableImpl().unlockSurface();
- }
+ }
}
- if (DEBUG) {
+ if ( DEBUG_TRACE_SWITCH ) {
if(created) {
- System.err.println(getThreadName() + ": Create GL context OK: " + toHexString(contextHandle) + " for " + getClass().getName()+" - "+getGLVersion());
+ System.err.println(getThreadName() + ": Create GL context OK: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName()+" - "+getGLVersion());
+ // Thread.dumpStack();
} else {
- System.err.println(getThreadName() + ": Create GL context FAILED for " + getClass().getName());
+ System.err.println(getThreadName() + ": Create GL context FAILED obj " + toHexString(hashCode()) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName());
}
- }
+ }
if(!created) {
return CONTEXT_NOT_CURRENT;
}
-
+
// finalize mapping the available GLVersions, in case it's not done yet
- {
+ {
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
-
- if( !GLContext.getAvailableGLVersionsSet(device) ) {
- final int reqMajor;
- final int reqProfile;
- if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_ES) ) {
- // ES1 or ES2
- reqMajor = ctxMajorVersion;
- reqProfile = GLContext.CTX_PROFILE_ES;
- } else {
- if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) {
+
+ // 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( ctxVersion.compareTo(Version300) <= 0 ) {
reqMajor = 2;
} else {
- reqMajor = ctxMajorVersion;
+ reqMajor = ctxVersion.getMajor();
}
if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE) ) {
reqProfile = GLContext.CTX_PROFILE_CORE;
} else {
reqProfile = GLContext.CTX_PROFILE_COMPAT;
}
- }
- GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
- ctxMajorVersion, ctxMinorVersion, ctxOptions);
- GLContext.setAvailableGLVersionsSet(device);
- if (DEBUG) {
- System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile,
+ ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ GLContext.setAvailableGLVersionsSet(device);
+
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": createContextOLD-MapVersionsAvailable HAVE: " + device+" -> "+reqMajor+"."+reqProfile+ " -> "+getGLVersion());
+ }
}
}
}
@@ -537,30 +724,44 @@ public abstract class GLContextImpl extends GLContext {
return CONTEXT_CURRENT;
}
protected abstract void makeCurrentImpl() throws GLException;
-
- /**
+
+ /**
+ * Calls {@link GLDrawableImpl#associateContext(GLContext, boolean)}
+ */
+ protected void associateDrawable(boolean bound) {
+ drawable.associateContext(this, bound);
+ }
+
+ /**
+ * Calls {@link GLDrawableImpl#contextMadeCurrent(GLContext, boolean)}
+ */
+ protected void contextMadeCurrent(boolean current) {
+ drawable.contextMadeCurrent(this, current);
+ }
+
+ /**
* Platform dependent entry point for context creation.<br>
*
* This method is called from {@link #makeCurrentWithinLock()} .. {@link #makeCurrent()} .<br>
*
- * The implementation shall verify this context with a
+ * The implementation shall verify this context with a
* <code>MakeContextCurrent</code> call.<br>
*
* 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
* @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
+ * The implementation shall verify this context with a
* <code>MakeContextCurrent</code> call.<br>
*
* The implementation <b>must</b> leave the context current.<br>
@@ -582,8 +783,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}.
@@ -616,13 +816,10 @@ public abstract class GLContextImpl extends GLContext {
* @see #createContextARBImpl
* @see #destroyContextARBImpl
*/
- protected final long createContextARB(long share, boolean direct)
+ protected final long createContextARB(final long share, final boolean direct)
{
- AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- GLProfile glp = glCaps.getGLProfile();
- GLProfile glpImpl = glp.getImpl();
+ final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB: mappedVersionsAvailableSet("+device.getConnection()+"): "+
@@ -631,64 +828,166 @@ public abstract class GLContextImpl extends GLContext {
if ( !GLContext.getAvailableGLVersionsSet(device) ) {
if(!mapGLVersions(device)) {
- // none of the ARB context creation calls was successful, bail out
+ // none of the ARB context creation calls was successful, bail out
return 0;
}
}
- int reqMajor;
- if(glpImpl.isGL4()) {
- reqMajor=4;
- } else if (glpImpl.isGL3()) {
- reqMajor=3;
- } else /* if (glpImpl.isGL2()) */ {
- reqMajor=2;
- }
+ final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ GLContext.getRequestMajorAndCompat(glCaps.getGLProfile(), reqMajorCTP);
- boolean compat = glpImpl.isGL2(); // incl GL3bc and GL4bc
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARB: Requested "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[0], null));
+ }
int _major[] = { 0 };
int _minor[] = { 0 };
int _ctp[] = { 0 };
long _ctx = 0;
-
- if( GLContext.getAvailableGLVersion(device, reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE,
+ 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(AbstractGraphicsDevice device) {
synchronized (GLContext.deviceVersionAvailable) {
+ final long t0 = ( DEBUG ) ? System.nanoTime() : 0;
boolean success = false;
// Following GLProfile.GL_PROFILE_LIST_ALL order of profile detection { GL4bc, GL3bc, GL2, GL4, GL3, GL2GL3, GLES2, GL2ES2, GLES1, GL2ES1 }
- success |= createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc
- success |= createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc
- success |= createContextARBMapVersionsAvailable(2, true /* compat */); // GL2
- success |= createContextARBMapVersionsAvailable(4, false /* core */); // GL4
- success |= createContextARBMapVersionsAvailable(3, false /* core */); // GL3
+ boolean hasGL4bc = false;
+ boolean hasGL3bc = false;
+ boolean hasGL2 = false;
+ boolean hasGL4 = false;
+ boolean hasGL3 = false;
+
+ // 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( !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( !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 ) {
+ 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;
+ }
+ 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 ) {
+ hasGL3bc = createContextARBMapVersionsAvailable(3, CTX_PROFILE_COMPAT); // GL3bc
+ success |= hasGL3bc;
+ if( hasGL3bc ) {
+ if(!hasGL3) { // last chance .. ignore hw-accel
+ GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ hasGL3 = true;
+ }
+ 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 ) {
+ hasGL2 = createContextARBMapVersionsAvailable(2, CTX_PROFILE_COMPAT); // GL2
+ success |= hasGL2;
+ if( hasGL2 ) {
+ resetStates(false); // clean this context states, since creation was temporary
+ }
+ }
if(success) {
// only claim GL versions set [and hence detected] if ARB context creation was successful
GLContext.setAvailableGLVersionsSet(device);
+ 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());
+ }
} else if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB-MapVersions NONE for :"+device);
- }
+ }
return success;
}
}
- private final boolean createContextARBMapVersionsAvailable(int reqMajor, boolean compat) {
+ /**
+ * 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) {
long _context;
- int reqProfile = compat ? CTX_PROFILE_COMPAT : CTX_PROFILE_CORE ;
- int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE; // default
- if(compat) {
- ctp &= ~CTX_PROFILE_CORE ;
- ctp |= CTX_PROFILE_COMPAT ;
- }
+ 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,
@@ -698,104 +997,93 @@ public abstract class GLContextImpl extends GLContext {
int major[] = new int[1];
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,
- // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts
+ // our minimum desktop OpenGL runtime requirements are 1.1,
+ // nevertheless we restrict ARB context creation to 2.0 to spare us futile attempts
majorMax=3; minorMax=0;
majorMin=2; minorMin=0;
}
- _context = createContextARBVersions(0, true, ctp,
+ _context = createContextARBVersions(0, true, ctp,
/* max */ majorMax, minorMax,
/* min */ majorMin, minorMin,
/* res */ major, minor);
- if(0==_context && !compat) {
+ if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) {
// try w/ FORWARD instead of CORE
ctp &= ~CTX_PROFILE_CORE ;
ctp |= CTX_OPTION_FORWARD ;
- _context = createContextARBVersions(0, true, ctp,
+ _context = createContextARBVersions(0, true, ctp,
/* 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 ;
ctp |= CTX_PROFILE_COMPAT ;
- _context = createContextARBVersions(0, true, ctp,
+ _context = createContextARBVersions(0, true, ctp,
/* max */ majorMax, minorMax,
/* min */ majorMin, minorMin,
/* res */ major, minor);
}
}
- if(0!=_context) {
- AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
- // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by
+ final boolean res;
+ if( 0 != _context ) {
+ 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());
}
- // only reset [and hence modify] this context state if ARB context creation was successful
- resetStates();
- return true;
+ res = true;
} else {
if (DEBUG) {
System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable NOPE: "+reqMajor+"."+reqProfile);
- }
- return false;
+ }
+ res = false;
}
+ return res;
}
- private final long createContextARBVersions(long share, boolean direct, int ctxOptionFlags,
- int majorMax, int minorMax,
- int majorMin, int minorMin,
+ private final long createContextARBVersions(long share, boolean direct, int ctxOptionFlags,
+ int majorMax, int minorMax,
+ int majorMin, int minorMin,
int major[], int minor[]) {
major[0]=majorMax;
minor[0]=minorMax;
long _context=0;
- boolean ok = false;
-
- while ( !ok &&
- GLContext.isValidGLVersion(major[0], minor[0]) &&
- ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) {
+ int i=0;
+ 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(GL3.GL_MAJOR_VERSION, hasMajor, 0);
- gl.glGetIntegerv(GL3.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;
}
@@ -805,52 +1093,31 @@ public abstract class GLContextImpl extends GLContext {
// As a last resort, the GL_VERSION string may be used ..
//
- /**
- * If major > 0 || minor > 0 : Use passed values, determined at creation time
- * If major==0 && minor == 0 : Use GL_VERSION
+ /**
+ * 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) {
- if (0==ctp) {
+ private final void setContextVersion(int major, int minor, int ctp, VersionNumberString glVendorVersion, boolean useGL) {
+ if ( 0 == ctp ) {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
- if(major>0 || minor>0) {
- if (!GLContext.isValidGLVersion(major, minor)) {
- GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
- throw e;
- }
- ctxMajorVersion = major;
- ctxMinorVersion = minor;
- ctxOptions = ctp;
- if(setVersionString) {
- ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION));
- }
- return;
- }
-
- if(major==0 && minor==0) {
- String versionStr = getGL().glGetString(GL.GL_VERSION);
- if(null==versionStr) {
- throw new GLException("GL_VERSION is NULL: "+this);
- }
- ctxOptions = ctp;
-
- // Set version
- GLVersionNumber version = new GLVersionNumber(versionStr);
- if (version.isValid()) {
- ctxMajorVersion = version.getMajor();
- ctxMinorVersion = version.getMinor();
- // We cannot promote a non ARB context to >= 3.1,
- // reduce it to 3.0 then.
- if ( ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
- && 0 == (ctxOptions & CTX_IS_ARB_CREATED) ) {
- ctxMajorVersion = 3;
- ctxMinorVersion = 0;
- }
- if(setVersionString) {
- ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr);
- }
- return;
+ ctxVersion = new VersionNumber(major, minor, 0);
+ ctxVersionString = getGLVersion(major, minor, ctp, glVersion);
+ ctxVendorVersion = glVendorVersion;
+ ctxOptions = ctp;
+ 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( ctxGLSLVersion.isZero() ) {
+ ctxGLSLVersion = getStaticGLSLVersionNumber(major, minor, ctxOptions);
+ }
}
}
}
@@ -859,18 +1126,18 @@ public abstract class GLContextImpl extends GLContext {
// 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(GLProfile glp, boolean glObject, 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);
+ return ReflectionUtil.instanceOf(instance, glp.getGLImplBaseClassName()+suffix);
}
/** Create the GL for this context. */
protected GL createGL(GLProfile glp) {
- GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } );
-
+ final GL gl = (GL) createInstance(glp, true, new Object[] { glp, this } );
+
/* FIXME: refactor dependence on Java 2D / JOGL bridge
if (tracker != null) {
gl.setObjectTracker(tracker);
@@ -878,11 +1145,32 @@ 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(GL gl) {
+ Method finalizeInit = null;
+ try {
+ finalizeInit = ReflectionUtil.getMethod(gl.getClass(), "finalizeInit", new Class<?>[]{ });
+ } catch ( Throwable t ) {
+ if(DEBUG) {
+ System.err.println("Catched "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ if( null != finalizeInit ) {
+ ReflectionUtil.callMethod(gl, finalizeInit, new Object[]{ });
+ }
+ }
+
public final ProcAddressTable getGLProcAddressTable() {
return glProcAddressTable;
}
-
+
/**
* Shall return the platform extension ProcAddressTable,
* ie for GLXExt, EGLExt, ..
@@ -890,18 +1178,22 @@ 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.
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglAllocateMemoryNV</code> /
+ * <code>glXAllocateMemoryNV</code>.
+ * </p>
*/
- public abstract void bindPbufferToTexture();
+ 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.
+ * Part of <code>GL_NV_vertex_array_range</code>.
+ * <p>
+ * Provides platform-independent access to the <code>wglFreeMemoryNV</code> /
+ * <code>glXFreeMemoryNV</code>.
+ * </p>
*/
- public abstract void releasePbufferFromTexture();
-
- 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
@@ -918,8 +1210,8 @@ public abstract class GLContextImpl extends GLContext {
/** Maps the given "platform-independent" extension name to a real
function name. Currently this is only used to map
- "GL_ARB_pbuffer" to "WGL_ARB_pbuffer/GLX_SGIX_pbuffer" and
- "GL_ARB_pixel_format" to "WGL_ARB_pixel_format/n.a."
+ "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();
@@ -933,41 +1225,118 @@ 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 void initGLRendererStrings() {
+ 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.");
- Thread.dumpStack();
+ 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) {
+ if(DEBUG) {
+ System.err.println("Warning: GL_RENDERER is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ glRenderer = _glRenderer;
+ glRendererLowerCase = glRenderer.toLowerCase();
+
+ final String _glVersion = glGetStringInt(GL.GL_VERSION, _glGetString);
+ if(null == _glVersion) {
// FIXME
- System.err.println("Warning: GL_RENDERER is NULL.");
- Thread.dumpStack();
- } else {
- glRenderer = _glRenderer;
- glRendererLowerCase = glRenderer.toLowerCase();
+ if(DEBUG) {
+ System.err.println("Warning: GL_VERSION is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ glVersion = _glVersion;
+
+ return true;
+ }
+ }
+
+ /**
+ * 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(int ctp, String glVersionStr) {
+ if( null != glVersionStr ) {
+ final GLVersionNumber version = GLVersionNumber.create(glVersionStr);
+ if ( version.isValid() ) {
+ int[] major = new int[] { version.getMajor() };
+ int[] minor = new int[] { version.getMinor() };
+ if ( GLContext.isValidGLVersion(ctp, major[0], minor[0]) ) {
+ return new VersionNumber(major[0], minor[0], 0);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 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(int[] glIntMajor, 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(GL2GL3.GL_MAJOR_VERSION, glIntMajor, 0, _glGetIntegerv);
+ glGetIntegervInt(GL2GL3.GL_MINOR_VERSION, glIntMinor, 0, _glGetIntegerv);
+ return true;
}
}
-
- protected final String getGLRendererString(boolean lowerCase) {
- return lowerCase ? glRendererLowerCase : glRenderer;
+
+ 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.
@@ -975,33 +1344,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. quering 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(boolean force, int major, int minor, int ctxProfileBits,
+ boolean strictMatch, 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( getGLDrawable().getGLProfile() ) );
}
updateGLXProcAddressTable();
- initGLRendererStrings();
-
- if(!isCurrentContextHardwareRasterizer()) {
- ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
- }
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( !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 {
+ // 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);
+ }
+ }
+ }
+
+ 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);
+ }
+
+ final boolean versionGL3IntOK;
+ {
+ // 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 {
+ versionValidated = false;
+ }
+ }
+ 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 (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 ) ;
+ }
+
+ 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;
+ }
+
+ if(!isCurrentContextHardwareRasterizer()) {
+ ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
+ }
+
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
- System.err.println(getThreadName() + ": Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
}
//
@@ -1011,7 +1574,7 @@ public abstract class GLContextImpl extends GLContext {
synchronized(mappedContextTypeObjectLock) {
table = mappedGLProcAddress.get( contextFQN );
if(null != table && !verifyInstance(gl.getGLProfile(), "ProcAddressTable", table)) {
- throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+
+ throw new InternalError("GLContext GL ProcAddressTable mapped key("+contextFQN+" - " + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+
") -> "+ table.getClass().getName()+" not matching "+gl.getGLProfile().getGLImplBaseClassName());
}
}
@@ -1021,8 +1584,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) {
@@ -1032,7 +1594,7 @@ public abstract class GLContextImpl extends GLContext {
}
}
}
-
+
//
// Update ExtensionAvailabilityCache
//
@@ -1047,7 +1609,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);
@@ -1055,116 +1617,430 @@ public abstract class GLContextImpl extends GLContext {
System.err.println(getThreadName() + ": GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(extensionAvailability.hashCode()) + " - entries: "+extensionAvailability.getTotalExtensionCount());
}
}
- }
- if( isExtensionAvailable("GL_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;
}
- protected final void removeCachedVersion(int major, int minor, int ctxProfileBits) {
+ private final void setRendererQuirks(final AbstractGraphicsDevice adevice, final GLDrawableFactoryImpl factory,
+ int reqMajor, int reqMinor, int reqCTP,
+ int major, int minor, int ctp, final VersionNumberString vendorVersion,
+ boolean withinGLVersionsMapping) {
+ int[] quirks = new int[GLRendererQuirks.COUNT + 1]; // + 1 ( NoFullFBOSupport )
+ int i = 0;
+
+ 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 = !isDriverMesa && ( glVendor.contains("ATI Technologies") || glRenderer.startsWith("ATI ") );
+ final boolean isDriverNVIDIAGeForce = !isDriverMesa && ( glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ") );
+
+ //
+ // 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[i++] = quirk;
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ } else {
+ // FIXME: Remove when moving EGL/ES to ARB ctx creation
+ synchronized(GLContextImpl.class) {
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ }
+ }
+ }
+ }
+
+ //
+ // 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[i++] = 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[i++] = quirk;
+ if( withinGLVersionsMapping ) {
+ // Thread safe due to single threaded initialization!
+ GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1);
+ }
+ }
+ 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[i++] = 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[i++] = quirk;
+ }
+ }
+ } else if( isWindows ) {
+ //
+ // WINDOWS
+ //
+ {
+ final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks[i++] = 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[i++] = 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[i++] = 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[i++] = 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[i++] = 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[i++] = quirk;
+ }
+ } else if( isDriverATICatalyst ) {
+ {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
+ }
+ quirks[i++] = quirk;
+ }
+ } else if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+ {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
+ }
+ quirks[i++] = quirk;
+ }
+ }
+ }
+ }
+
+
+ //
+ // RENDERER related quirks
+ //
+ if( isDriverMesa ) {
+ 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[i++] = quirk;
+ }
+ if( hwAccel /* glRenderer.contains( MesaRendererIntelsp ) || glRenderer.contains( MesaRendererAMDsp ) */ )
+ {
+ final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks[i++] = 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[i++] = quirk;
+ }
+ if( glRenderer.contains( MesaRendererIntelsp ) &&
+ vendorVersion.compareTo(mesaIntelBuggySharedCtx921) >= 0 && isX11 ) {
+ final int quirk = GLRendererQuirks.GLSharedContextBuggy;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks[i++] = quirk;
+ }
+ if( isWindows && glRenderer.contains("SVGA3D") ) {
+ final VersionNumber mesaSafeFBOVersion = new VersionNumber(8, 0, 0);
+ if ( vendorVersion.compareTo(mesaSafeFBOVersion) < 0 ) { // includes: vendorVersion.isZero()
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer + " / Mesa-Version "+vendorVersion);
+ }
+ quirks[i++] = quirk;
+ }
+ }
+ }
+
+ //
+ // Property related quirks
+ //
+ if( FORCE_MIN_FBO_SUPPORT ) {
+ final int quirk = GLRendererQuirks.NoFullFBOSupport;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: property");
+ }
+ quirks[i++] = quirk;
+ }
+
+ glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
+ if(DEBUG) {
+ System.err.println("Quirks local.0: "+glRendererQuirks);
+ }
+ {
+ // Merge sticky quirks, thread safe due to single threaded initialization!
+ GLRendererQuirks.pushStickyDeviceQuirks(adevice, glRendererQuirks);
+
+ final AbstractGraphicsDevice factoryDefaultDevice = factory.getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(factoryDefaultDevice, adevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, glRendererQuirks);
+ }
+ if( esCtx ) {
+ final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) &&
+ !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, glRendererQuirks);
+ }
+ }
+ }
+ if(DEBUG) {
+ System.err.println("Quirks local.X: "+glRendererQuirks);
+ System.err.println("Quirks sticky on "+adevice+": "+GLRendererQuirks.getStickyDeviceQuirks(adevice));
+ }
+ }
+
+ private 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 (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
+ }
+
+ private final void removeCachedVersion(int major, int minor, int ctxProfileBits) {
if(!isCurrentContextHardwareRasterizer()) {
ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
}
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
-
+
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
System.err.println(getThreadName() + ": RM Context FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
}
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));
}
}
}
private final boolean isCurrentContextHardwareRasterizer() {
boolean isHardwareRasterizer = true;
-
+
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 */
+ glRendererLowerCase.contains("llvmpipe") /* Gallium */
);
}
return isHardwareRasterizer;
}
-
+
/**
* Updates the platform's 'GLX' function cache
*/
protected abstract void updateGLXProcAddressTable();
protected abstract StringBuilder getPlatformExtensionsStringImpl();
-
+
+ @Override
public final boolean isFunctionAvailable(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) {}
}
// Check platform extensions 2nd (cached) - context had to be enabled once
- final ProcAddressTable pTable = getPlatformExtProcAddressTable();
- if(null!=pTable) {
+ final ProcAddressTable pTable = getPlatformExtProcAddressTable();
+ if(null!=pTable) {
try {
- if(0!=pTable.getAddressFor(glFunctionName)) {
+ if( pTable.isFunctionAvailable( glFunctionName ) ) {
return true;
}
} catch (Exception e) {}
}
// dynamic function lookup at last incl name aliasing (not cached)
- DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
- String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true);
- long addr = 0;
- int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase);
- for(int i = 0; 0==addr && i < variants; i++) {
- String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i);
+ final DynamicLookupHelper dynLookup = getDrawableImpl().getGLDynamicLookupHelper();
+ final String tmpBase = GLNameResolver.normalizeVEN(GLNameResolver.normalizeARB(glFunctionName, true), true);
+ boolean res = false;
+ 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);
+ res = dynLookup.isFunctionAvailable(tmp);
} catch (Exception e) { }
}
- if(0!=addr) {
- return true;
- }
- return false;
+ return res;
}
- public boolean isExtensionAvailable(String glExtensionName) {
+ @Override
+ public final boolean isExtensionAvailable(String glExtensionName) {
if(null!=extensionAvailability) {
return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName));
}
return false;
}
+ @Override
public final int getPlatformExtensionCount() {
return null != extensionAvailability ? extensionAvailability.getPlatformExtensionCount() : 0;
}
-
+
+ @Override
public final String getPlatformExtensionsString() {
if(null!=extensionAvailability) {
return extensionAvailability.getPlatformExtensionsString();
@@ -1172,10 +2048,12 @@ public abstract class GLContextImpl extends GLContext {
return null;
}
+ @Override
public final int getGLExtensionCount() {
return null != extensionAvailability ? extensionAvailability.getGLExtensionCount() : 0;
}
-
+
+ @Override
public final String getGLExtensionsString() {
if(null!=extensionAvailability) {
return extensionAvailability.getGLExtensionsString();
@@ -1189,15 +2067,15 @@ public abstract class GLContextImpl extends GLContext {
}
return false;
}
-
+
protected static String getContextFQN(AbstractGraphicsDevice device, int major, int minor, int ctxProfileBits) {
// remove non-key values
- ctxProfileBits &= ~( GLContext.CTX_OPTION_DEBUG | GLContext.CTX_IMPL_ES2_COMPAT ) ;
-
+ ctxProfileBits &= CTX_IMPL_CACHE_MASK;
+
return device.getUniqueID() + "-" + toHexString(composeBits(major, minor, ctxProfileBits));
}
- protected String getContextFQN() {
+ protected final String getContextFQN() {
return contextFQN;
}
@@ -1208,32 +2086,63 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Not supported on non-pbuffer contexts");
}
- /** 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();
+ @Override
+ public int getDefaultPixelDataType() {
+ evalPixelDataType();
+ return pixelDataType;
+ }
- /** 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) {
+ synchronized(this) {
+ if(!pixelDataEvaluated) {
+ 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;
}
@@ -1242,38 +2151,123 @@ 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(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>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) {
+ if(0 > framebufferName) {
+ return; // ignore invalid name
+ }
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ boundFBOTarget[0] = framebufferName; // draw
+ break;
+ case GL2GL3.GL_READ_FRAMEBUFFER:
+ boundFBOTarget[1] = framebufferName; // read
+ break;
+ default: // ignore untracked target
+ }
+ }
+ @Override
+ public final int getBoundFramebuffer(int target) {
+ switch(target) {
+ case GL.GL_FRAMEBUFFER:
+ case GL2GL3.GL_DRAW_FRAMEBUFFER:
+ return boundFBOTarget[0]; // draw
+ case GL2GL3.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(); }
+ @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
//
+ @Override
public final String getGLDebugMessageExtension() {
return glDebugHandler.getExtension();
}
+ @Override
public final boolean isGLDebugMessageEnabled() {
return glDebugHandler.isEnabled();
}
-
+
+ @Override
public final int getContextCreationFlags() {
- return additionalCtxCreationFlags;
+ return additionalCtxCreationFlags;
}
+ @Override
public final void setContextCreationFlags(int flags) {
if(!isCreated()) {
additionalCtxCreationFlags = flags & GLContext.CTX_OPTION_DEBUG;
}
}
-
- public final boolean isGLDebugSynchronous() { return glDebugHandler.isSynchronous(); }
-
+
+ @Override
+ public final boolean isGLDebugSynchronous() { return glDebugHandler.isSynchronous(); }
+
+ @Override
public final void setGLDebugSynchronous(boolean synchronous) {
glDebugHandler.setSynchronous(synchronous);
}
-
+
+ @Override
public final void enableGLDebugMessage(boolean enable) throws GLException {
if(!isCreated()) {
if(enable) {
@@ -1286,40 +2280,48 @@ public abstract class GLContextImpl extends GLContext {
glDebugHandler.enable(enable);
}
}
-
- public final void addGLDebugListener(GLDebugListener listener) {
+
+ @Override
+ public final void addGLDebugListener(GLDebugListener listener) {
glDebugHandler.addListener(listener);
}
-
+
+ @Override
public final void removeGLDebugListener(GLDebugListener listener) {
glDebugHandler.removeListener(listener);
- }
-
+ }
+
+ @Override
public final void glDebugMessageControl(int source, int type, int severity, int count, IntBuffer ids, 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) {
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) {
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..c057c904c 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,39 +56,39 @@ 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 Map<GLContext, ShareSet> shareMap = new IdentityHashMap<GLContext, ShareSet>();
private static final Object dummyValue = new Object();
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, Object> allShares = new IdentityHashMap<GLContext, Object>();
+ private final Map<GLContext, Object> createdShares = new IdentityHashMap<GLContext, Object>();
+ private final Map<GLContext, Object> destroyedShares = new IdentityHashMap<GLContext, Object>();
- public void add(GLContext ctx) {
+ public void add(final GLContext ctx) {
if (allShares.put(ctx, dummyValue) == null) {
if (ctx.isCreated()) {
createdShares.put(ctx, dummyValue);
} else {
destroyedShares.put(ctx, dummyValue);
}
- }
+ }
}
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();
+
+ public GLContext getCreatedShare(final GLContext ignore) {
+ for (final Iterator<GLContext> iter = createdShares.keySet().iterator(); iter.hasNext(); ) {
+ final GLContext ctx = iter.next();
if (ctx != ignore) {
return ctx;
}
@@ -95,21 +96,21 @@ public class GLContextShareSet {
return null;
}
- public void contextCreated(GLContext ctx) {
- Object res = destroyedShares.remove(ctx);
+ public void contextCreated(final GLContext ctx) {
+ final 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 " +
+ final Object res2 = createdShares.put(ctx, dummyValue);
+ assert res2 == null : "State of ShareSet corrupted; thought context " +
ctx + " shouldn't have been in created set but was";
}
- public void contextDestroyed(GLContext ctx) {
- Object res = createdShares.remove(ctx);
+ public void contextDestroyed(final GLContext ctx) {
+ final 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 " +
+ final Object res2 = destroyedShares.put(ctx, dummyValue);
+ assert res2 == null : "State of ShareSet corrupted; thought context " +
ctx + " shouldn't have been in destroyed set but was";
}
}
@@ -117,7 +118,7 @@ public class GLContextShareSet {
/** Indicate that contexts <code>share1</code> and
<code>share2</code> will share textures and display lists. Both
must be non-null. */
- public static synchronized void registerSharing(GLContext share1, GLContext share2) {
+ public static synchronized void registerSharing(final GLContext share1, final GLContext share2) {
if (share1 == null || share2 == null) {
throw new IllegalArgumentException("Both share1 and share2 must be non-null");
}
@@ -133,12 +134,12 @@ public class GLContextShareSet {
addEntry(share1, share);
addEntry(share2, share);
if (DEBUG) {
- System.err.println("GLContextShareSet: registereSharing: 1: " +
+ System.err.println("GLContextShareSet: registereSharing: 1: " +
toHexString(share1.getHandle()) + ", 2: " + toHexString(share2.getHandle()));
- }
+ }
}
- 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");
}
@@ -155,9 +156,9 @@ public class GLContextShareSet {
throw new GLException("Last context's share set contains no destroyed context");
}
if (DEBUG) {
- System.err.println("GLContextShareSet: unregisterSharing: " +
+ System.err.println("GLContextShareSet: unregisterSharing: " +
toHexString(lastContext.getHandle())+", entries: "+s.size());
- }
+ }
for(Iterator<GLContext> iter = s.iterator() ; iter.hasNext() ; ) {
GLContext ctx = iter.next();
if(null == removeEntry(ctx)) {
@@ -165,61 +166,85 @@ public class GLContextShareSet {
}
}
}
-
- 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 one created GLContext shared with the given <code>context</code>, otherwise return <code>null</code>. */
+ public static synchronized GLContext getCreatedShare(final GLContext context) {
+ final ShareSet share = entryFor(context);
+ if (share == null) {
+ return null;
}
- return null;
+ return share.getCreatedShare(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(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 +252,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 +262,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(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 b950c2fdf..2c947693c 100644
--- a/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
+++ b/src/jogl/classes/jogamp/opengl/GLDebugMessageHandler.java
@@ -27,6 +27,8 @@
*/
package jogamp.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import javax.media.nativewindow.NativeWindowException;
@@ -37,68 +39,62 @@ import javax.media.opengl.GLException;
import com.jogamp.common.os.Platform;
import com.jogamp.gluegen.runtime.ProcAddressTable;
-import jogamp.opengl.gl4.GL4bcProcAddressTable;
+import com.jogamp.opengl.GLExtensions;
/**
* 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 {
- /** Extension <i>GL_ARB_debug_output</i> implementing GLDebugMessage */
- public static final String GL_ARB_debug_output = "GL_ARB_debug_output".intern();
-
- /** Extension <i>GL_AMD_debug_output</i> implementing GLDebugMessage */
- public static final String GL_AMD_debug_output = "GL_AMD_debug_output".intern();
-
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(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) {
if(DEBUG) {
System.err.println("GLDebugMessageHandler.init("+enable+")");
@@ -110,18 +106,31 @@ 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 (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()) {
// Currently buggy, ie. throws an exception after leaving the native callback.
@@ -131,101 +140,103 @@ public class GLDebugMessageHandler {
}
return;
}
- if( ctx.isExtensionAvailable(GL_ARB_debug_output) ) {
- extName = GL_ARB_debug_output;
+ if( ctx.isExtensionAvailable(GLExtensions.ARB_debug_output) ) {
+ extName = GLExtensions.ARB_debug_output;
extType = EXT_ARB;
- } else if( ctx.isExtensionAvailable(GL_AMD_debug_output) ) {
- extName = GL_AMD_debug_output;
+ } else if( ctx.isExtensionAvailable(GLExtensions.AMD_debug_output) ) {
+ extName = GLExtensions.AMD_debug_output;
extType = EXT_AMD;
}
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());
}
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 == GL_ARB_debug_output;
+ return extName == GLExtensions.ARB_debug_output;
}
-
+
public final boolean isExtensionAMD() {
- return extName == GL_AMD_debug_output;
+ 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) {
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(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS);
} else {
- ctx.getGL().glDisable(GL2GL3.GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
- }
+ ctx.getGL().glDisable(GL2GL3.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 {
ctx.validateCurrent();
@@ -233,7 +244,7 @@ public class GLDebugMessageHandler {
return;
}
enableImpl(enable);
- }
+ }
final void enableImpl(boolean enable) throws GLException {
if(enable) {
if(0 == handle) {
@@ -247,19 +258,19 @@ 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) {
listenerImpl.addListener(-1, listener);
}
@@ -267,11 +278,11 @@ public class GLDebugMessageHandler {
public final void addListener(int index, GLDebugListener listener) {
listenerImpl.addListener(index, listener);
}
-
+
public final void removeListener(GLDebugListener listener) {
listenerImpl.removeListener(listener);
}
-
+
private final void sendMessage(GLDebugMessage msg) {
synchronized(listenerImpl) {
if(DEBUG) {
@@ -283,25 +294,26 @@ public class GLDebugMessageHandler {
}
}
}
-
+
public static class StdErrGLDebugListener implements GLDebugListener {
boolean threadDump;
-
+
public StdErrGLDebugListener(boolean threadDump) {
this.threadDump = threadDump;
}
+ @Override
public void messageSent(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) {
final GLDebugMessage event = new GLDebugMessage(ctx, System.currentTimeMillis(), source, type, id, severity, msg);
sendMessage(event);
@@ -311,11 +323,11 @@ public class GLDebugMessageHandler {
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 3c60eb699..c914b5e10 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.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,7 +47,9 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.SurfaceChangeable;
+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;
@@ -55,10 +57,16 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
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
@@ -66,29 +74,70 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
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 (GLException gle) {
+ if(DEBUG) {
+ System.err.println("Catched 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);
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getContext();
}
return null;
}
- protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
-
+
+ @Override
+ protected final boolean createSharedResourceImpl(AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.isValid();
+ }
+ return false;
+ }
+
+ @Override
+ public final GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getRendererQuirks();
+ }
+ return null;
+ }
+
/**
* Returns the shared device mapped to the <code>device</code> {@link AbstractGraphicsDevice#getConnection()},
* either a preexisting or newly created, or <code>null</code> if creation failed or not supported.<br>
@@ -97,25 +146,14 @@ 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;
+ 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
* @param profile if EGL/ES, profile <code>1</code> refers to ES1 and <code>2</code> to ES2,
* otherwise the profile is ignored.
@@ -125,32 +163,48 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
- public GLDrawable createGLDrawable(NativeSurface target) {
+ @Override
+ public final GLDrawable createGLDrawable(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile());
GLDrawable result = null;
adevice.lock();
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
- // layered surface -> Offscreen/PBuffer
- final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
- chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice));
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
+
+ // layered surface -> Offscreen/[FBO|PBuffer]
+ if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) {
+ throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
+ }
config.setChosenCapabilities(chosenCapsMod);
+ ols.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer");
+ System.err.println("chosenCaps: "+chosenCaps);
+ System.err.println("chosenCapsMod: "+chosenCapsMod);
+ System.err.println("OffscreenLayerSurface: **** "+ols);
+ System.err.println("Target: **** "+target);
+ Thread.dumpStack();
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
}
- result = createOffscreenDrawableImpl(target);
+ if( chosenCapsMod.isFBO() ) {
+ result = createFBODrawableImpl(target, chosenCapsMod, 0);
+ } else {
+ result = createOffscreenDrawableImpl(target);
+ }
} else if(chosenCaps.isOnscreen()) {
// onscreen
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target);
}
@@ -158,12 +212,20 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
} else {
// offscreen
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO chosen / avail, PBuffer: "+
+ chosenCaps.isFBO()+" / "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target);
+ }
+ if( ! ( target instanceof MutableSurface ) ) {
+ throw new IllegalArgumentException("Passed NativeSurface must implement MutableSurface for offscreen: "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
- throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
+ if( chosenCaps.isFBO() && isFBOAvailable ) {
+ // 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 {
+ result = createOffscreenDrawableImpl(target);
}
- result = createOffscreenDrawableImpl(target);
}
} finally {
adevice.unlock();
@@ -176,128 +238,256 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Onscreen GLDrawable construction
+ // Onscreen GLDrawable construction
//
protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target);
//---------------------------------------------------------------------------
//
- // PBuffer GLDrawable construction
+ // PBuffer Offscreen GLAutoDrawable construction
//
- public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ @Override
+ public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp);
- public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
+ @Override
+ public final GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
int width,
int height,
GLContext shareWith) {
- if(height<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ 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 support not available with device: "+device);
- }
-
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
- GLDrawableImpl drawable = null;
- device.lock();
- try {
- drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
- if(null != drawable) {
- drawable.setRealized(true);
- }
- } finally {
- device.unlock();
+ if ( !canCreateGLPbuffer(device, capsRequested.getGLProfile()) ) {
+ throw new GLException("Pbuffer not available with device: "+device);
}
- if(null==drawable) {
- throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height);
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
+ final GLDrawableImpl drawable = createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser,
+ new UpstreamSurfaceHookMutableSize(width, height) ) );
+ if(null != drawable) {
+ drawable.setRealized(true);
}
- return new GLPbufferImpl( drawable, shareWith);
- }
+ return new GLPbufferImpl( drawable, (GLContextImpl) drawable.createContext(shareWith) );
+ }
//---------------------------------------------------------------------------
//
- // Offscreen GLDrawable construction
+ // Offscreen GLDrawable construction
//
- protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+ @Override
+ public final boolean canCreateFBO(AbstractGraphicsDevice deviceReq, GLProfile glp) {
+ AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ if(null == device) {
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ return GLContext.isFBOAvailable(device, glp);
+ }
+
+ @Override
+ public final 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);
+ if(drawable instanceof GLFBODrawableImpl) {
+ return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, context, null, null );
+ }
+ return new GLOffscreenAutoDrawableImpl( drawable, context, null, null);
+ }
+
+ @Override
+ public final GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice deviceReq,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height );
+ drawable.setRealized(true);
+ if(drawable instanceof GLFBODrawableImpl) {
+ return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, null, null, null );
+ }
+ return new GLOffscreenAutoDrawableImpl( drawable, null, null, null);
+ }
- public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
+ @Override
+ public final GLAutoDrawable createDummyAutoDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ final GLDrawable drawable = createDummyDrawable(deviceReq, createNewDevice, capsRequested, chooser);
+ drawable.setRealized(true);
+ final GLAutoDrawable sharedDrawable = new GLAutoDrawableDelegate(drawable, null, null, true /*ownDevice*/, null) { };
+ return sharedDrawable;
+ }
+
+ @Override
+ public final GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
- int width,
- int height) {
+ int width, int height) {
if(width<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
- device.lock();
- try {
- return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
- } finally {
- device.unlock();
+ 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) ) );
}
- public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ @Override
+ public final GLDrawable createDummyDrawable(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ final AbstractGraphicsDevice device = createNewDevice ? getOrCreateSharedDevice(deviceReq) : deviceReq;
if(null == device) {
- throw new GLException("No shared device for requested: "+deviceReq);
+ throw new GLException("No shared device for requested: "+deviceReq+", createNewDevice "+createNewDevice);
+ }
+ if( !createNewDevice ) {
+ device.lock();
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
- device.lock();
try {
- return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, 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 unrealized FBO offscreen GLDrawable */
+ protected final GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) {
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit);
+ }
+
+ /** Creates a platform dependent unrealized offscreen pbuffer/pixmap GLDrawable instance */
+ protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+
/**
- * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well,
- * so the windowing system related implementation is able to set the surface handle.
+ * Creates a mutable {@link ProxySurface} w/o defined surface handle.
+ * <p>
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}.
+ * </p>
+ * <p>
+ * 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 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
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height);
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook);
- public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ /**
+ * 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 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 as returned by {@link NativeSurface#getWidth()}, 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,
+ * The latter is platform specific and small
+ *
+ * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
+ */
+ public final ProxySurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
- throw new GLException("No shared device for requested: "+device);
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ 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 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.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()}, 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 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) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ if(null == device) {
+ throw new GLException("No shared device for requested: "+deviceReq);
+ }
+ if(0 == windowHandle) {
+ throw new IllegalArgumentException("Null windowHandle");
}
device.lock();
try {
- return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser);
+ return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream);
} finally {
device.unlock();
}
- }
-
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+ }
+
+ /**
+ * Creates a {@link ProxySurface} with a set surface handle.
+ * <p>
+ * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance.
+ * </p>
+ * @param upstream TODO
+ */
+ protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
//---------------------------------------------------------------------------
//
@@ -305,25 +495,17 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//
protected abstract GLContext createExternalGLContextImpl();
-
+
+ @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();
}
@@ -342,17 +524,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
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
@@ -399,7 +570,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* 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,
@@ -436,16 +607,16 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
rampEntry = 0.0f;
gammaRamp[i] = rampEntry;
}
- registerGammaShutdownHook();
+ needsGammaRampReset = true;
return setGammaRamp(gammaRamp);
}
+ @Override
public synchronized void resetDisplayGamma() {
- if (gammaShutdownHook == null) {
- throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first");
+ if( needsGammaRampReset ) {
+ resetGammaRamp(originalGammaRamp);
+ needsGammaRampReset = false;
}
- resetGammaRamp(originalGammaRamp);
- unregisterGammaShutdownHook();
}
//------------------------------------------------------
@@ -477,34 +648,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
}
// 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() {
- public void run() {
- synchronized (GLDrawableFactoryImpl.this) {
- resetGammaRamp(originalGammaRamp);
- }
- }
- });
- 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
- }
+ private volatile Buffer originalGammaRamp;
+ private volatile boolean needsGammaRampReset = false;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index c992b3cb2..0e135d5e0 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,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,34 +41,52 @@
package jogamp.opengl;
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.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.GLFBODrawable;
import javax.media.opengl.GLRunnable;
-
-import com.jogamp.opengl.util.Animator;
+import javax.media.opengl.GLSharedContextSetter;
/** 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 = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
+ }
+
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
- private Object listenersLock = new Object();
- private ArrayList<GLEventListener> listeners;
- private HashSet<GLEventListener> listenersToBeInit;
+ 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 boolean autoSwapBufferMode;
- private Thread skipContextReleaseThread;
- private Object glRunnablesLock = new Object();
- private ArrayList<GLRunnable> glRunnables;
+ 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();
@@ -76,15 +94,76 @@ public class GLDrawableHelper {
public final void reset() {
synchronized(listenersLock) {
- listeners = new ArrayList<GLEventListener>();
- listenersToBeInit = new HashSet<GLEventListener>();
+ listeners.clear();
+ listenersToBeInit.clear();
}
autoSwapBufferMode = true;
- skipContextReleaseThread = null;
+ exclusiveContextThread = null;
+ exclusiveContextSwitch = 0;
synchronized(glRunnablesLock) {
- glRunnables = new ArrayList<GLRunnable>();
+ glRunnables.clear();
}
animatorCtrl = null;
+ sharedContext = null;
+ sharedAutoDrawable = null;
+ }
+
+ public final void setSharedContext(GLContext thisContext, 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(GLAutoDrawable thisAutoDrawable, 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(GLContext[] shared) {
+ final GLContext shareWith;
+ final boolean pending;
+ if ( null != sharedAutoDrawable ) {
+ final boolean allGLELInitialized;
+ if( sharedAutoDrawable instanceof GLSharedContextSetter ) {
+ allGLELInitialized = ((GLSharedContextSetter)sharedAutoDrawable).areAllGLEventListenerInitialized();
+ } else {
+ allGLELInitialized = true; // we have to assume 'yes'
+ }
+ shareWith = sharedAutoDrawable.getContext();
+ pending = null == shareWith || !shareWith.isCreated() || !allGLELInitialized;
+ } else {
+ shareWith = sharedContext;
+ pending = null != shareWith && !shareWith.isCreated();
+ }
+ shared[0] = shareWith;
+ return pending;
}
@Override
@@ -105,6 +184,207 @@ public class GLDrawableHelper {
return sb.toString();
}
+ /** Limit release calls of {@link #forceNativeRelease(GLContext)} to {@value}. */
+ private static final int MAX_RELEASE_ITER = 512;
+
+ /**
+ * 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>
+ * This methods continues calling {@link GLContext#release()} until the context has been natively released.
+ * </p>
+ * @param ctx
+ */
+ public static final void forceNativeRelease(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>
+ * The <code>oldCtx</code> will be destroyed if <code>destroyPrevCtx</code> is <code>true</code>,
+ * otherwise dis-associate <code>oldCtx</code> from <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
+ * </p>
+ * <p>
+ * Re-associate <code>newCtx</code> with <code>drawable</code>
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ * </p>
+ * <p>
+ * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * </p>
+ * <p>
+ * No locking is being performed on the drawable, caller is required to take care of it.
+ * </p>
+ *
+ * @param drawable the drawable which context is changed
+ * @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)}
+ *
+ * @see GLAutoDrawable#setContext(GLContext, boolean)
+ */
+ public static final void switchContext(GLDrawable drawable, GLContext oldCtx, boolean destroyOldCtx, GLContext newCtx, int newCtxCreationFlags) {
+ if( null != oldCtx ) {
+ if( destroyOldCtx ) {
+ oldCtx.destroy();
+ } else {
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
+ }
+ }
+
+ if(null!=newCtx) {
+ newCtx.setContextCreationFlags(newCtxCreationFlags);
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
+ }
+ }
+
+ /**
+ * If the drawable is not realized, OP is a NOP.
+ * <ul>
+ * <li>release context if current</li>
+ * <li>destroy old drawable</li>
+ * <li>create new drawable</li>
+ * <li>attach new drawable to context</li>
+ * <li>make context current, if it was current</li>
+ * </ul>
+ * <p>
+ * 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) {
+ if( ! drawable.isRealized() ) {
+ return drawable;
+ }
+ 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( null != context ) {
+ // Ensure to sync GL command stream
+ if( currentContext != context ) {
+ context.makeCurrent();
+ }
+ context.getGL().glFinish();
+ context.setGLDrawable(null, true); // dis-associate
+ }
+
+ if(null != proxySurface) {
+ proxySurface.enableUpstreamSurfaceHookLifecycle(false);
+ }
+ try {
+ drawable.setRealized(false);
+ drawable = (GLDrawableImpl) factory.createGLDrawable(surface); // [2]
+ drawable.setRealized(true);
+ } finally {
+ if(null != proxySurface) {
+ proxySurface.enableUpstreamSurfaceHookLifecycle(true);
+ }
+ }
+
+ if(null != context) {
+ context.setGLDrawable(drawable, true); // re-association
+ }
+
+ 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.
+ * </p>
+ * <p>
+ * May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)}
+ * in case of a a pbuffer- or pixmap-drawable.
+ * </p>
+ * <p>
+ * FBO drawables are resized w/o drawable destruction.
+ * </p>
+ * <p>
+ * 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
+ * @param newHeight the new height, it's minimum is capped to 1
+ * @return the new drawable in case of an pbuffer/pixmap drawable, otherwise the passed drawable is being returned.
+ * @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
+ {
+ final NativeSurface ns = drawable.getNativeSurface();
+ final int lockRes = ns.lockSurface();
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
+ throw new NativeWindowException("Could not lock surface of drawable: "+drawable);
+ }
+ boolean validateSize = true;
+ try {
+ 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);
+ } 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() ) {
+ ((GLFBODrawable) drawable).resetSize(context.getGL());
+ }
+ } else {
+ drawable = GLDrawableHelper.recreateGLDrawable(drawable, context);
+ }
+ } finally {
+ ns.unlockSurface();
+ }
+ if( validateSize && ( drawable.getWidth() != newWidth || drawable.getHeight() != newHeight ) ) {
+ throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable);
+ }
+ return drawable;
+ }
+
public final void addGLEventListener(GLEventListener listener) {
addGLEventListener(-1, listener);
}
@@ -117,88 +397,296 @@ 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(GLEventListener listener) {
synchronized(listenersLock) {
- listeners.remove(listener);
listenersToBeInit.remove(listener);
+ return listeners.remove(listener) ? listener : null;
+ }
+ }
+
+ public final GLEventListener removeGLEventListener(int index) throws IndexOutOfBoundsException {
+ synchronized(listenersLock) {
+ if(0>index) {
+ index = listeners.size()-1;
+ }
+ 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(GLEventListener listener) {
+ synchronized(listenersLock) {
+ return !listenersToBeInit.contains(listener);
+ }
+ }
+
+ public final void setGLEventListenerInitState(GLEventListener listener, 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 GLEventListener disposeGLEventListener(GLAutoDrawable autoDrawable, GLEventListener listener, 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
*/
- public final void dispose(GLAutoDrawable drawable) {
+ public final int disposeAllGLEventListener(GLAutoDrawable autoDrawable, boolean remove) {
+ int disposeCount = 0;
synchronized(listenersLock) {
- 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) ) {
+ listener.dispose(autoDrawable);
+ disposeCount++;
+ }
+ }
+ } else {
+ for (int i = 0; i < listeners.size(); i++) {
+ final GLEventListener listener = listeners.get(i);
+ if( !listenersToBeInit.contains(listener) ) {
+ listener.dispose(autoDrawable);
+ listenersToBeInit.add(listener);
+ disposeCount++;
+ }
+ }
}
}
+ return disposeCount;
}
-
- private boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) {
- if(listenersToBeInit.remove(l)) {
- l.init(drawable);
- if(sendReshape) {
- reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false);
+
+ /**
+ * 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;
}
- return true;
}
- return false;
+ 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];
}
- public final void init(GLAutoDrawable drawable) {
- synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
+ /**
+ * 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) {
- // If make current ctx, 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 the must always be initialized unconditional.
- listenersToBeInit.add(listener);
+ final boolean isPaused = isAnimatorAnimatingOnOtherThread() && animatorCtrl.pause();
- if ( ! init( listener, drawable, false ) ) {
- throw new GLException("GLEventListener "+listener+" already initialized: "+drawable);
+ 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(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape, boolean setViewport) {
+ l.init(drawable);
+ if(sendReshape) {
+ reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), setViewport, false /* checkInit */);
+ }
+ }
+
+ /**
+ * 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(GLAutoDrawable drawable, boolean sendReshape) {
+ synchronized(listenersLock) {
+ final ArrayList<GLEventListener> _listeners = listeners;
+ 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 GLEventListener
+ drawable.getGL().glViewport(0, 0, drawable.getWidth(), drawable.getHeight());
}
}
}
public final void display(GLAutoDrawable drawable) {
displayImpl(drawable);
- if(!execGLRunnables(drawable)) {
- displayImpl(drawable);
+ if( glRunnables.size()>0 && !execGLRunnables(drawable) ) { // glRunnables volatile OK; execGL.. only executed if size > 0
+ displayImpl(drawable);
}
}
- private void displayImpl(GLAutoDrawable drawable) {
+ private final void displayImpl(GLAutoDrawable drawable) {
synchronized(listenersLock) {
- for (int i=0; i < listeners.size(); i++) {
- final GLEventListener listener = listeners.get(i) ;
- // GLEventListener may need to be init,
+ 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
- init( listener, drawable, true ) ;
+ if( listenersToBeInit.remove(listener) ) {
+ init( listener, drawable, true /* sendReshape */, listenersToBeInit.size() + 1 == listenerCount /* setViewport if 1st init */ );
+ }
listener.display(drawable);
}
}
}
- private void reshape(GLEventListener listener, GLAutoDrawable drawable,
- int x, int y, int width, int height, boolean setViewport, boolean checkInit) {
+ private final void reshape(GLEventListener listener, GLAutoDrawable drawable,
+ int x, int y, int width, int height, boolean setViewport, boolean checkInit) {
if(checkInit) {
- // GLEventListener may need to be init,
- // in case this one is added after the realization of the GLAutoDrawable
- init( listener, drawable, false ) ;
+ // GLEventListener may need to be init,
+ // in case this one is added after the realization of the GLAutoDrawable
+ synchronized(listenersLock) {
+ if( listenersToBeInit.remove(listener) ) {
+ listener.init(drawable);
+ }
+ }
}
if(setViewport) {
+ final GL gl = drawable.getGL();
+ final int glerr0 = gl.glGetError();
+ if( GL.GL_NO_ERROR != glerr0 ) {
+ System.err.println("Info: GLDrawableHelper.reshape: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
drawable.getGL().glViewport(x, y, width, height);
}
listener.reshape(drawable, x, y, width, height);
@@ -207,30 +695,51 @@ public class GLDrawableHelper {
public final void reshape(GLAutoDrawable drawable, int x, int y, int width, 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 boolean execGLRunnables(GLAutoDrawable drawable) {
+ private final boolean execGLRunnables(GLAutoDrawable drawable) { // glRunnables.size()>0
boolean res = true;
- if(glRunnables.size()>0) {
+ // 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;
+ }
+ }
+ return res;
+ }
+
+ public final void flushGLRunnables() {
+ if(glRunnables.size()>0) { // volatile OK
// swap one-shot list asap
- ArrayList<GLRunnable> _glRunnables = null;
+ final ArrayList<GLRunnableTask> _glRunnables;
synchronized(glRunnablesLock) {
if(glRunnables.size()>0) {
_glRunnables = glRunnables;
- glRunnables = new ArrayList<GLRunnable>();
+ 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;
+ _glRunnables.get(i).flush();
}
}
}
- return res;
}
public final void setAnimator(GLAnimatorControl animator) throws GLException {
@@ -248,15 +757,15 @@ public class GLDrawableHelper {
}
}
- public final boolean isExternalAnimatorRunning() {
+ 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 ;
}
@@ -264,17 +773,35 @@ public class GLDrawableHelper {
return ( null != animatorCtrl ) ? animatorCtrl.isAnimating() : false ;
}
- public final void invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) {
- if( null == drawable || null == glRunnable ) {
- return;
+ /**
+ * <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>
+ * {@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>
+ *
+ * @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>.
+ */
+ public final boolean invoke(GLAutoDrawable drawable, boolean wait, GLRunnable glRunnable) {
+ if( null == glRunnable || null == drawable ||
+ wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
+ return false;
}
- Throwable throwable = null;
+
GLRunnableTask rTask = null;
Object rTaskLock = new Object();
+ Throwable throwable = null;
synchronized(rTaskLock) {
- boolean deferred;
+ final boolean deferred;
synchronized(glRunnablesLock) {
- deferred = isExternalAnimatorAnimating();
+ deferred = isAnimatorAnimatingOnOtherThread();
if(!deferred) {
wait = false; // don't wait if exec immediatly
}
@@ -299,6 +826,60 @@ public class GLDrawableHelper {
}
}
}
+ return true;
+ }
+
+ public final boolean invoke(GLAutoDrawable drawable, boolean wait, List<GLRunnable> newGLRunnables) {
+ if( null == newGLRunnables || newGLRunnables.size() == 0 || null == drawable ||
+ wait && ( !drawable.isRealized() || null==drawable.getContext() ) ) {
+ return false;
+ }
+
+ final int count = newGLRunnables.size();
+ GLRunnableTask rTask = null;
+ Object rTaskLock = new Object();
+ Throwable throwable = null;
+ synchronized(rTaskLock) {
+ final boolean deferred;
+ synchronized(glRunnablesLock) {
+ deferred = isAnimatorAnimatingOnOtherThread() || !drawable.isRealized();
+ if(!deferred) {
+ wait = false; // don't wait if exec immediately
+ }
+ for(int i=0; i<count-1; i++) {
+ 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 */);
+ glRunnables.add(rTask);
+ }
+ if( !deferred ) {
+ drawable.display();
+ } else if( wait ) {
+ try {
+ rTaskLock.wait(); // free lock, allow execution of rTask
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rTask.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ return true;
+ }
+
+ public final void enqueue(GLRunnable glRunnable) {
+ if( null == glRunnable) {
+ return;
+ }
+ synchronized(glRunnablesLock) {
+ glRunnables.add( new GLRunnableTask(glRunnable, null, false) );
+ }
}
public final void setAutoSwapBufferMode(boolean enable) {
@@ -309,25 +890,74 @@ 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(Thread t, 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 (Throwable ex) {
+ ex.printStackTrace();
+ throw new GLException(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<Runnable> perThreadInitAction = new ThreadLocal<Runnable>();
/** Principal helper method which runs a Runnable with the context
@@ -346,104 +976,76 @@ 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");
+ Exception e = new GLException(getThreadName()+" Info: GLDrawableHelper " + this + ".invokeGL(): NULL GLContext");
e.printStackTrace();
}
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
*/
- 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, boolean destroyContext) {
// 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 {
+ // utilize recursive locking
lastInitAction = perThreadInitAction.get();
lastContext.release();
}
}
- int res = GLContext.CONTEXT_NOT_CURRENT;
-
+
+ int res;
try {
res = context.makeCurrent();
- 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();
- }
- runnable.run();
- if (autoSwapBufferMode) {
- drawable.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);
- }
+ if (GLContext.CONTEXT_NOT_CURRENT != res) {
+ if(GLContext.CONTEXT_CURRENT_NEW == res) {
+ throw new GLException(getThreadName()+" GLDrawableHelper " + this + ".invokeGL(): Dispose case (no init action given): Native context was not created (new ctx): "+context);
+ }
+ if( listeners.size() > 0 && null != autoDrawable ) {
+ disposeAllGLEventListener(autoDrawable, false);
}
}
} finally {
try {
- if(isDisposeAction) {
+ if(destroyContext) {
context.destroy();
- } else if( res != GLContext.CONTEXT_NOT_CURRENT ) {
- context.release();
+ } else {
+ forceNativeRelease(context);
}
+ flushGLRunnables();
} catch (Exception e) {
- System.err.println("Catched: "+e.getMessage());
+ System.err.println("Catched Exception on thread "+getThreadName());
e.printStackTrace();
}
if (lastContext != null) {
@@ -454,99 +1056,206 @@ public class GLDrawableHelper {
}
}
}
-
- 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();
+
+ // 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 = perThreadInitAction.get();
+ lastContext.release();
+ }
+ }
+
try {
- if(isDisposeAction) {
- context.destroy();
- ctxDestroyed = true;
- } else if( res != GLContext.CONTEXT_NOT_CURRENT &&
- (null == skipContextReleaseThread || currentThread != skipContextReleaseThread) ) {
- context.release();
- ctxReleased = true;
+ final boolean releaseContext;
+ if( GLContext.CONTEXT_NOT_CURRENT == res ) {
+ res = context.makeCurrent();
+ releaseContext = !_isExclusiveThread;
+ } else {
+ releaseContext = _releaseExclusiveThread;
+ }
+ if (GLContext.CONTEXT_NOT_CURRENT != res) {
+ try {
+ 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();
+ }
+ } finally {
+ if( _releaseExclusiveThread ) {
+ exclusiveContextThread = null;
+ if (DEBUG) {
+ System.err.println("GLDrawableHelper.invokeGL() - Release ExclusiveContextThread -- currentThread "+Thread.currentThread());
+ }
+ }
+ if( releaseContext ) {
+ try {
+ context.release();
+ } catch (Exception e) {
+ System.err.println("Catched Exception on thread "+getThreadName());
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ } finally {
+ if (lastContext != null) {
+ final int res2 = lastContext.makeCurrent();
+ if (null != lastInitAction && res2 == GLContext.CONTEXT_CURRENT_NEW) {
+ lastInitAction.run();
+ }
}
- } catch (Exception e) {
- System.err.println("Catched: "+e.getMessage());
- e.printStackTrace();
+ }
+ }
+
+ private final void invokeGLImplStats(final GLDrawable drawable,
+ final GLContext context,
+ final Runnable runnable,
+ final Runnable initAction) {
+ final Thread currentThread = Thread.currentThread();
+
+ // 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;
}
- tdX = System.currentTimeMillis() - tdX; // release / destroy
+ // 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 = perThreadInitAction.get();
+ 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);
+
+ 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 {
+ 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 {
+ perThreadInitAction.set(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
+ }
+ } 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 (Exception e) {
+ System.err.println("Catched Exception on thread "+getThreadName());
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ } 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();
+ }
+ }
+ }
+ 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 36f17e5a1..d11274560 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.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 jogamp.opengl;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
@@ -50,173 +52,301 @@ 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(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
+ this(factory, comp, (GLCapabilitiesImmutable) comp.getGraphicsConfiguration().getRequestedCapabilities(), realized);
+ }
+
+ protected GLDrawableImpl(GLDrawableFactory factory, NativeSurface comp, GLCapabilitiesImmutable requestedCapabilities, boolean realized) {
this.factory = factory;
this.surface = comp;
this.realized = realized;
- this.requestedCapabilities = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getRequestedCapabilities();
+ this.requestedCapabilities = requestedCapabilities;
}
- /**
+ /**
* Returns the DynamicLookupHelper
*/
public abstract GLDynamicLookupHelper getGLDynamicLookupHelper();
- public GLDrawableFactoryImpl getFactoryImpl() {
+ public final GLDrawableFactoryImpl getFactoryImpl() {
return (GLDrawableFactoryImpl) getFactory();
}
- /** For offscreen GLDrawables (pbuffers and "pixmap" drawables),
- indicates that native resources should be reclaimed. */
- public void destroy() {
- surface.getGraphicsConfiguration().getScreen().getDevice().lock();
- try {
- destroyImpl();
- } finally {
- surface.getGraphicsConfiguration().getScreen().getDevice().unlock();
- }
- }
- protected void destroyImpl() {
- throw new GLException("Should not call this (should only be called for offscreen GLDrawables)");
- }
-
+ @Override
public final void swapBuffers() throws GLException {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
- if ( caps.getDoubleBuffered() ) {
- if(!surface.surfaceSwap()) {
- 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();
+ if( !realized ) { // volatile OK (locked below)
+ return; // destroyed already
+ }
+ final int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
+ if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+ return;
+ }
+ try {
+ 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();
- } finally {
- unlockSurface();
+ swapBuffersImpl(false);
}
}
- } else {
- GLContext ctx = GLContext.getCurrent();
- if(null!=ctx && ctx.getGLDrawable()==this) {
- ctx.getGL().glFinish();
- }
+ } finally {
+ unlockSurface();
}
surface.surfaceUpdated(this, surface, System.currentTimeMillis());
}
- protected abstract void swapBuffersImpl();
- public static String toHexString(long hex) {
+ /**
+ * Platform and implementation depending surface swap.
+ * <p>The surface is locked.</p>
+ * <p>
+ * 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
+ * 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) {
return "0x" + Long.toHexString(hex);
}
- public GLProfile getGLProfile() {
+ @Override
+ public final GLProfile getGLProfile() {
return requestedCapabilities.getGLProfile();
}
+ @Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
return (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
}
- public GLCapabilitiesImmutable getRequestedGLCapabilities() {
+ public final GLCapabilitiesImmutable getRequestedGLCapabilities() {
return requestedCapabilities;
}
+ @Override
public NativeSurface getNativeSurface() {
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() {
return surface.getSurfaceHandle();
}
- public GLDrawableFactory getFactory() {
+ @Override
+ public final GLDrawableFactory getFactory() {
return factory;
}
- public final synchronized void setRealized(boolean realizedArg) {
- if ( realized != realizedArg ) {
+ @Override
+ public final void setRealized(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();
if(realizedArg) {
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
- throw new GLException("GLDrawableImpl.setRealized(true): already realized, but surface not ready (lockSurface)");
+ if(isProxySurface) {
+ ((ProxySurface)surface).createNotify();
+ }
+ if(NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface()) {
+ throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
}
} else {
aDevice.lock();
}
- try {
- setRealizedImpl();
- if(realizedArg) {
- updateHandle();
- } else {
- destroyHandle();
+ try {
+ if ( realized != realizedArg ) { // volatile: OK
+ realized = realizedArg;
+ if(realizedArg) {
+ setRealizedImpl();
+ createHandle();
+ } else {
+ destroyHandle();
+ setRealizedImpl();
+ }
}
} finally {
if(realizedArg) {
- unlockSurface();
+ surface.unlockSurface();
} else {
aDevice.unlock();
+ if(isProxySurface) {
+ ((ProxySurface)surface).destroyNotify();
+ }
}
}
} else if(DEBUG) {
System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg);
}
}
+
+ /**
+ * Platform specific realization of drawable
+ */
protected abstract void setRealizedImpl();
-
- public synchronized boolean isRealized() {
+
+ /**
+ * 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>bound</code> is <code>true</code>, the context is current and being newly associated w/ this drawable.
+ * </p>
+ * <p>
+ * 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>
+ * 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 associateContext(GLContext ctx, 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.
+ * </p>
+ * <p>
+ * If <code>current</code> is <code>false</code>, the context is still current and will be release after this method returns.
+ * </p>
+ * <p>
+ * Being called by {@link GLContextImpl#contextMadeCurrent(boolean)}.
+ * </p>
+ * @see #associateContext(GLContext, boolean)
+ */
+ protected void contextMadeCurrent(GLContext glc, 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(GL gl, 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 boolean isRealized() {
return realized;
}
+ @Override
public int getWidth() {
return surface.getWidth();
}
-
+
+ @Override
public int getHeight() {
return surface.getHeight();
}
- public int lockSurface() throws GLException {
- return surface.lockSurface();
+ @Override
+ public boolean isGLOriented() {
+ return true;
}
- public void unlockSurface() {
- surface.unlockSurface();
+ /**
+ * {@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 {
+ 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;
+
}
- public boolean isSurfaceLocked() {
- return surface.isSurfaceLocked();
+ /**
+ * {@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();
}
+ @Override
public String toString() {
return getClass().getSimpleName()+"[Realized "+isRealized()+
",\n\tFactory "+getFactory()+
- ",\n\thandle "+toHexString(getHandle())+
- ",\n\tWindow "+getNativeSurface()+"]";
+ ",\n\tHandle "+toHexString(getHandle())+
+ ",\n\tSurface "+getNativeSurface()+"]";
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
-
- protected GLDrawableFactory factory;
- protected NativeSurface surface;
- protected GLCapabilitiesImmutable requestedCapabilities;
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
+
+ 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
@@ -228,6 +358,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..421f06205 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,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,7 +36,7 @@ public class GLDynamicLookupHelper extends DynamicLibraryBundle {
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
new file mode 100644
index 000000000..6f5fa3eed
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -0,0 +1,593 @@
+package jogamp.opengl;
+
+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.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
+
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.opengl.FBObject;
+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}.
+ * <p>
+ * It utilizes the context lifecycle hook {@link #contextRealized(GLContext, boolean)}
+ * to initialize the {@link FBObject} instance.
+ * </p>
+ * <p>
+ * 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;
+ protected static final boolean DEBUG_SWAP;
+
+ static {
+ Debug.initSingleton();
+ DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
+ DEBUG_SWAP = DEBUG || Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true);
+ }
+
+ private final GLDrawableImpl parent;
+ private GLCapabilitiesImmutable origParentChosenCaps;
+
+ private boolean initialized;
+ 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 int pendingFBOReset = -1;
+ /** Indicated whether the FBO is bound. */
+ private boolean fboBound;
+ /** Indicated 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);
+ }
+
+ /**
+ * @param factory
+ * @param parent
+ * @param surface
+ * @param fboCaps the requested FBO capabilities
+ * @param textureUnit
+ */
+ protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface,
+ GLCapabilitiesImmutable fboCaps, int textureUnit) {
+ super(factory, surface, fboCaps, false);
+ this.initialized = false;
+
+ this.parent = parent;
+ this.origParentChosenCaps = getChosenGLCapabilities(); // just to avoid null, will be reset at initialize(..)
+ this.texUnit = textureUnit;
+ this.samples = fboCaps.getNumSamples();
+ fboResetQuirk = false;
+
+ // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+ // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ;
+
+ this.swapBufferContext = null;
+ }
+
+ private final void initialize(boolean realize, 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 GLCapabilities chosenFBOCaps = (GLCapabilities) getChosenGLCapabilities(); // cloned at setRealized(true)
+
+ final int maxSamples = gl.getMaxRenderbufferSamples();
+ {
+ 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( chosenFBOCaps.getDoubleBuffered() ) {
+ fbosN = bufferCount;
+ } else {
+ fbosN = 1;
+ }
+
+ fbos = new FBObject[fbosN];
+ fboIBack = 0; // head
+ fboIFront = fbos.length - 1; // tail
+
+ for(int i=0; i<fbosN; i++) {
+ fbos[i] = new FBObject();
+ fbos[i].reset(gl, getWidth(), getHeight(), samples, false);
+ if(fbos[i].getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+i+"] "+fbos[i]);
+ }
+ if(samples > 0) {
+ fbos[i].attachColorbuffer(gl, 0, chosenFBOCaps.getAlphaBits()>0);
+ } else {
+ fbos[i].attachTexture2D(gl, 0, chosenFBOCaps.getAlphaBits()>0);
+ }
+ if( chosenFBOCaps.getStencilBits() > 0 ) {
+ fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
+ } else {
+ fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
+ }
+ fbos[fboIFront].resetSamplingSink(gl);
+
+ fbos[0].formatToGLCapabilities(chosenFBOCaps);
+ chosenFBOCaps.setDoubleBuffered( chosenFBOCaps.getDoubleBuffered() || samples > 0 );
+ } else {
+ for(int i=0; i<fbos.length; i++) {
+ fbos[i].destroy(gl);
+ }
+ fbos=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) {
+ swapBufferContext = sbc;
+ }
+
+ private final void reset(GL gl, int idx, int width, int height, int samples, int alphaBits, int stencilBits) {
+ if( !fboResetQuirk ) {
+ try {
+ fbos[idx].reset(gl, width, height, samples, false);
+ if(fbos[idx].getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbos[idx]);
+ }
+ return;
+ } catch (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();
+ if(DEBUG) {
+ System.err.println(VersionUtil.getPlatformInfo());
+ System.err.println(joglVersion.toString());
+ System.err.println(JoglVersion.getGLInfo(gl, null));
+ } else {
+ System.err.println(joglVersion.getBriefOSGLBuildInfo(gl, null));
+ }
+ e.printStackTrace();
+ }
+ }
+ // 'fallthrough' intended
+ }
+ }
+ // resetQuirk fallback
+ fbos[idx].destroy(gl);
+ fbos[idx] = new FBObject();
+ fbos[idx].reset(gl, getWidth(), getHeight(), samples, false);
+ if(fbos[idx].getNumSamples() != samples) {
+ throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbos[idx]);
+ }
+ if(samples > 0) {
+ fbos[idx].attachColorbuffer(gl, 0, alphaBits>0);
+ } else {
+ fbos[idx].attachTexture2D(gl, 0, alphaBits>0);
+ }
+ if( stencilBits > 0 ) {
+ fbos[idx].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
+ } else {
+ fbos[idx].attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+ }
+ }
+
+ private final void reset(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;
+ if(DEBUG) {
+ System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): BEGIN - ctxSwitch "+ctxSwitch+", "+this);
+ Thread.dumpStack();
+ }
+ 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
+ fboSwapped = false;
+ try {
+ final int maxSamples = gl.getMaxRenderbufferSamples();
+ 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+"/"+maxSamples);
+ }
+ initialize(false, gl);
+ samples = newSamples;
+ initialize(true, gl);
+ } else {
+ if(DEBUG) {
+ System.err.println("GLFBODrawableImpl.reset(): simple reconfig: "+samples+" -> "+newSamples+"/"+maxSamples);
+ }
+ final int nWidth = getWidth();
+ final int nHeight = getHeight();
+ samples = newSamples;
+ 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( pendingFBOReset != i ) {
+ reset(gl, i, nWidth, nHeight, samples, caps.getAlphaBits(), caps.getStencilBits());
+ }
+ }
+ final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities();
+ fbos[0].formatToGLCapabilities(fboCapsNative);
+ }
+ } catch (Throwable t) {
+ tFBO = t;
+ } finally {
+ try {
+ ourContext.release();
+ if(ctxSwitch) {
+ curContext.makeCurrent();
+ }
+ } catch (Throwable t) {
+ tGL = t;
+ }
+ }
+ if(null != tFBO) {
+ throw new GLException("GLFBODrawableImpl.reset(..) FBObject.reset(..) exception", tFBO);
+ }
+ if(null != tGL) {
+ throw new GLException("GLFBODrawableImpl.reset(..) GLContext.release() exception", tGL);
+ }
+ if(DEBUG) {
+ System.err.println("GLFBODrawableImpl.reset(newSamples "+newSamples+"): END "+this);
+ }
+ }
+
+ //
+ // GLDrawable
+ //
+
+ @Override
+ public final GLContext createContext(GLContext shareWith) {
+ final GLContext ctx = parent.createContext(shareWith);
+ ctx.setGLDrawable(this, false);
+ return ctx;
+ }
+
+ //
+ // GLDrawableImpl
+ //
+
+ @Override
+ public final GLDynamicLookupHelper getGLDynamicLookupHelper() {
+ return parent.getGLDynamicLookupHelper();
+ }
+
+ @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(GL gl, boolean hasDedicatedDrawableRead) {
+ return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ;
+ }
+
+ @Override
+ protected final void setRealizedImpl() {
+ final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
+ if(realized) {
+ parent.setRealized(true);
+ origParentChosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities();
+ final GLCapabilities chosenFBOCaps = (GLCapabilities) origParentChosenCaps.cloneMutable();
+ chosenFBOCaps.copyFrom(getRequestedGLCapabilities());
+ msConfig.setChosenCapabilities(chosenFBOCaps);
+ } else {
+ msConfig.setChosenCapabilities(origParentChosenCaps);
+ parent.setRealized(false);
+ }
+ }
+
+ @Override
+ protected void associateContext(GLContext glc, boolean bound) {
+ initialize(bound, glc.getGL());
+ }
+
+ @Override
+ protected final void contextMadeCurrent(GLContext glc, boolean current) {
+ final GL gl = glc.getGL();
+ if(current) {
+ if( !initialized ) {
+ throw new GLException("Not initialized: "+this);
+ }
+ fbos[fboIBack].bind(gl);
+ fboBound = true;
+ 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) {
+ final GLContext ctx = GLContext.getCurrent();
+ 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 ) {
+ swapBufferContext.swapBuffers(doubleBuffered);
+ }
+ if(doPostSwap) {
+ swapFBOImplPost(ctx);
+ }
+ }
+
+ private final void swapFBOImplPost(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, getWidth(), getHeight(), samples, caps.getAlphaBits(), caps.getStencilBits());
+ pendingFBOReset = -1;
+ }
+ }
+
+ private final void swapFBOImpl(GLContext glc) {
+ final GL gl = glc.getGL();
+ fbos[fboIBack].markUnbound(); // fast path, use(gl,..) is called below
+
+ if(DEBUG) {
+ 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);
+ final TextureAttachment texAttachment;
+ if(colorbuffer instanceof TextureAttachment) {
+ texAttachment = (TextureAttachment) colorbuffer;
+ } 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);
+ }
+ }
+ gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
+ fbos[fboIFront].use(gl, texAttachment);
+
+ /* 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_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 {
+ reset(gl, samples);
+ }
+
+ @Override
+ public final int getTextureUnit() { return texUnit; }
+
+ @Override
+ public final void setTextureUnit(int u) { texUnit = u; }
+
+ @Override
+ public final int getNumSamples() { return samples; }
+
+ @Override
+ public void setNumSamples(GL gl, int newSamples) throws GLException {
+ if(samples != newSamples) {
+ reset(gl, newSamples);
+ }
+ }
+
+ @Override
+ public final int setNumBuffers(int bufferCount) throws GLException {
+ // FIXME: Implement
+ return 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 {
+ if(!initialized) {
+ return null;
+ }
+ final FBObject res;
+ switch(bufferName) {
+ case GL.GL_FRONT:
+ if( samples > 0 ) {
+ res = fbos[0].getSamplingSinkFBO();
+ } else {
+ res = fbos[fboIFront];
+ }
+ break;
+ case GL.GL_BACK:
+ res = fbos[fboIBack];
+ break;
+ default:
+ throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName));
+ }
+ return res;
+ }
+
+ @Override
+ public final TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException {
+ if(!initialized) {
+ return null;
+ }
+ final TextureAttachment res;
+ switch(bufferName) {
+ case GL.GL_FRONT:
+ if( samples > 0 ) {
+ res = fbos[0].getSamplingSink();
+ } else {
+ res = (TextureAttachment) 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);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName));
+ }
+ 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+
+ ",\n\tFactory "+getFactory()+
+ ",\n\tHandle "+toHexString(getHandle())+
+ ",\n\tCaps "+surface.getGraphicsConfiguration().getChosenCapabilities()+
+ ",\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 "+surface+
+ "]";
+ }
+
+ public static class ResizeableImpl extends GLFBODrawableImpl implements GLFBODrawable.Resizeable {
+ protected ResizeableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, ProxySurface surface,
+ GLCapabilitiesImmutable fboCaps, int textureUnit) {
+ super(factory, parent, surface, fboCaps, textureUnit);
+ }
+
+ @Override
+ public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException {
+ if(DEBUG) {
+ System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+getThreadName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ }
+ int lockRes = lockSurface();
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ throw new NativeWindowException("Could not lock surface: "+this);
+ }
+ try {
+ // propagate new size
+ final ProxySurface ps = (ProxySurface) getNativeSurface();
+ final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook();
+ if(ush instanceof UpstreamSurfaceHook.MutableSize) {
+ ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight);
+ } else {
+ throw new InternalError("GLFBODrawableImpl.ResizableImpl's ProxySurface doesn't hold a UpstreamSurfaceHookMutableSize but "+ush.getClass().getName()+", "+ps+", ush");
+ }
+ if( null != context && context.isCreated() ) {
+ resetSize(context.getGL());
+ }
+ } finally {
+ unlockSurface();
+ }
+ }
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
index 6fe9f080c..5c6b475b2 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationFactory.java
@@ -38,7 +38,7 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser;
public abstract class GLGraphicsConfigurationFactory extends GraphicsConfigurationFactory {
protected static int chooseCapabilities(CapabilitiesChooser chooser, CapabilitiesImmutable capsRequested,
- List /*<CapabilitiesImmutable>*/ availableCaps, int recommendedIndex) {
+ List<? extends CapabilitiesImmutable> availableCaps, int recommendedIndex) {
if (null == capsRequested) {
throw new NativeWindowException("Null requested capabilities");
}
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index d7958c7f1..702fb77de 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -28,17 +28,22 @@
package jogamp.opengl;
-import java.util.ArrayList;
-
+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.opengl.GLRendererQuirks;
public class GLGraphicsConfigurationUtil {
public static final String NV_coverage_sample = "NV_coverage_sample";
public static final int WINDOW_BIT = 1 << 0;
public static final int BITMAP_BIT = 1 << 1;
public static final int PBUFFER_BIT = 1 << 2;
- public static final int ALL_BITS = WINDOW_BIT | BITMAP_BIT | PBUFFER_BIT ;
+ 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) {
if(null==sb) {
@@ -61,74 +66,184 @@ public class GLGraphicsConfigurationUtil {
sb.append(", ");
}
sb.append("PBUFFER");
+ seperator=true;
+ }
+ if( 0 != ( FBO_BIT & winattrbits ) ) {
+ if(seperator) {
+ sb.append(", ");
+ }
+ sb.append("FBO");
}
return sb;
}
/**
- * @return bitmask representing the input boolean in exclusive or logic, ie only one bit will be set
- */
- public static final int getWinAttributeBits(boolean isOnscreen, boolean isPBuffer) {
+ public static final int getWinAttributeBits(boolean isOnscreen, boolean isFBO, boolean isPBuffer, boolean isBitmap) {
int winattrbits = 0;
if(isOnscreen) {
winattrbits |= WINDOW_BIT;
- } else if (!isPBuffer) {
+ }
+ if(isFBO) {
+ winattrbits |= FBO_BIT;
+ }
+ if(isPBuffer ){
+ winattrbits |= PBUFFER_BIT;
+ }
+ if(isBitmap) {
winattrbits |= BITMAP_BIT;
+ }
+ return winattrbits;
+ }
+ public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) {
+ return getWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap());
+ } */
+
+ /**
+ * @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) {
+ final int winattrbits;
+ if(isOnscreen) {
+ winattrbits = WINDOW_BIT;
+ } else if(isFBO) {
+ winattrbits = FBO_BIT;
+ } else if(isPBuffer ){
+ winattrbits = PBUFFER_BIT;
+ } else if(isBitmap) {
+ winattrbits = BITMAP_BIT;
} else {
- winattrbits |= PBUFFER_BIT;
+ throw new InternalError("Empty bitmask");
}
return winattrbits;
}
/**
- * @see #getWinAttributeBits(boolean, boolean)
+ * @see #getExclusiveWinAttributeBits(boolean, boolean, boolean, boolean)
*/
- public static final int getWinAttributeBits(GLCapabilitiesImmutable caps) {
- return getWinAttributeBits(caps.isOnscreen(), caps.isPBuffer());
+ public static final int getExclusiveWinAttributeBits(GLCapabilitiesImmutable caps) {
+ return getExclusiveWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap());
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public static final boolean addGLCapabilitiesPermutations(ArrayList capsBucket, GLCapabilitiesImmutable temp, int winattrbits) {
- int preSize = capsBucket.size();
- if( 0 != ( WINDOW_BIT & winattrbits ) ) {
- GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
- cpy.setOnscreen(true);
- capsBucket.add(cpy);
- }
- if( 0 != ( PBUFFER_BIT & winattrbits ) ) {
- GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
- cpy.setPBuffer(true);
- capsBucket.add(cpy);
+ public static final GLCapabilities fixWinAttribBitsAndHwAccel(AbstractGraphicsDevice device, int winattrbits, GLCapabilities caps) {
+ caps.setBitmap ( 0 != ( BITMAP_BIT & winattrbits ) );
+ caps.setPBuffer ( 0 != ( PBUFFER_BIT & winattrbits ) );
+ caps.setFBO ( 0 != ( FBO_BIT & winattrbits ) );
+ // we reflect availability semantics, hence setting onscreen at last (maybe overwritten above)!
+ caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) );
+
+ final int accel = GLContext.isHardwareRasterizer( device, caps.getGLProfile() );
+ if(0 == accel && caps.getHardwareAccelerated() ) {
+ caps.setHardwareAccelerated(false);
}
- if( 0 != ( BITMAP_BIT & winattrbits ) ) {
- GLCapabilities cpy = (GLCapabilities) temp.cloneMutable();
- cpy.setOnscreen(false);
- cpy.setPBuffer(false);
- capsBucket.add(cpy);
+
+ return caps;
+ }
+
+ /**
+ * 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(GLCapabilitiesImmutable capsRequested,
+ GLDrawableFactory factory, AbstractGraphicsDevice device) {
+ if( !capsRequested.isOnscreen() ) {
+ return fixOffscreenGLCapabilities(capsRequested, factory, device);
}
- return capsBucket.size() > preSize;
+ return capsRequested;
}
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
- if( !capsRequested.isOnscreen() ) {
- return fixOffScreenGLCapabilities(capsRequested, pbufferAvailable);
+ if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) {
+ // fix caps ..
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setBitmap (false);
+ caps2.setPBuffer (false);
+ caps2.setFBO (false);
+ caps2.setOnscreen(true);
+ return caps2;
}
return capsRequested;
}
- public static GLCapabilitiesImmutable fixOffScreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean pbufferAvailable)
+ public static GLCapabilitiesImmutable fixOffscreenBitOnly(GLCapabilitiesImmutable capsRequested)
{
- if( capsRequested.getDoubleBuffered() ||
- capsRequested.isOnscreen() ||
- ( !pbufferAvailable && capsRequested.isPBuffer() ) )
+ if( capsRequested.isOnscreen() ) {
+ // fix caps ..
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setOnscreen(false);
+ return caps2;
+ }
+ return capsRequested;
+ }
+
+ /**
+ * 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(GLCapabilitiesImmutable capsRequested,
+ 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() ) ;
+
+ if( capsRequested.isOnscreen() ||
+ useFBO != capsRequested.isFBO() ||
+ usePbuffer != capsRequested.isPBuffer() ||
+ useBitmap != capsRequested.isBitmap() ||
+ !doubleBufferAvailable && capsRequested.getDoubleBuffered() )
{
// fix caps ..
- GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
- caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
- if(caps2.isPBuffer() && !pbufferAvailable) {
- caps2.setPBuffer(false);
+ caps2.setFBO( useFBO );
+ caps2.setPBuffer( usePbuffer );
+ caps2.setBitmap( useBitmap );
+ if( !doubleBufferAvailable ) {
+ caps2.setDoubleBuffered(false);
}
return caps2;
}
@@ -137,28 +252,81 @@ public class GLGraphicsConfigurationUtil {
public static GLCapabilitiesImmutable fixGLPBufferGLCapabilities(GLCapabilitiesImmutable capsRequested)
{
- if( capsRequested.getDoubleBuffered() || capsRequested.isOnscreen() || !capsRequested.isPBuffer()) {
+ if( capsRequested.isOnscreen() ||
+ !capsRequested.isPBuffer() ||
+ capsRequested.isFBO() )
+ {
// fix caps ..
- GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
- caps2.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN - we don't need to be single buffered ..
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
caps2.setOnscreen(false);
+ caps2.setFBO(false);
caps2.setPBuffer(true);
+ caps2.setBitmap(false);
return caps2;
}
return capsRequested;
}
- public static GLCapabilitiesImmutable fixOpaqueGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean isOpaque)
+ /** Fix opaque setting while preserve alpha bits */
+ public static GLCapabilities fixOpaqueGLCapabilities(GLCapabilities capsRequested, boolean isOpaque)
{
- GLCapabilities caps2 = null;
-
if( capsRequested.isBackgroundOpaque() != isOpaque) {
- // fix caps ..
- caps2 = (GLCapabilities) capsRequested.cloneMutable();
- caps2.setBackgroundOpaque(isOpaque);
+ final int alphaBits = capsRequested.getAlphaBits();
+ capsRequested.setBackgroundOpaque(isOpaque);
+ capsRequested.setAlphaBits(alphaBits);
+ }
+ return capsRequested;
+ }
+
+ /** Fix double buffered setting */
+ public static GLCapabilitiesImmutable fixDoubleBufferedGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean doubleBuffered)
+ {
+ if( capsRequested.getDoubleBuffered() != doubleBuffered) {
+ final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable();
+ caps2.setDoubleBuffered(doubleBuffered);
return caps2;
}
return capsRequested;
}
-
+
+ public static GLCapabilitiesImmutable clipRGBAGLCapabilities(GLCapabilitiesImmutable caps, boolean allowRGB555, 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(GLCapabilitiesImmutable caps, 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
new file mode 100644
index 000000000..345f08e4c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
@@ -0,0 +1,140 @@
+/**
+ * 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;
+
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLOffscreenAutoDrawable;
+
+import com.jogamp.common.util.locks.RecursiveLock;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implements GLOffscreenAutoDrawable {
+
+ /**
+ * @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) {
+ super(drawable, context, upstreamWidget, true, lock);
+ }
+
+ @Override
+ public void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException {
+ this.defaultWindowResizedOp(newWidth, newHeight);
+ }
+
+ public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO {
+ /**
+ * @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) {
+ super(drawable, context, upstreamWidget, lock);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return ((GLFBODrawableImpl)drawable).isInitialized();
+ }
+
+ @Override
+ public final int getTextureUnit() {
+ return ((GLFBODrawableImpl)drawable).getTextureUnit();
+ }
+
+ @Override
+ public final void setTextureUnit(int unit) {
+ ((GLFBODrawableImpl)drawable).setTextureUnit(unit);
+ }
+
+ @Override
+ public final int getNumSamples() {
+ return ((GLFBODrawableImpl)drawable).getNumSamples();
+ }
+
+ @Override
+ public final void setNumSamples(GL gl, int newSamples) throws GLException {
+ ((GLFBODrawableImpl)drawable).setNumSamples(gl, newSamples);
+ windowRepaintOp();
+ }
+
+ @Override
+ public final int setNumBuffers(int bufferCount) throws 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() {
+ return ((GLFBODrawableImpl)drawable).getDoubleBufferMode();
+ }
+
+ @Override
+ public void setDoubleBufferMode(DoubleBufferMode mode) throws GLException {
+ ((GLFBODrawableImpl)drawable).setDoubleBufferMode(mode);
+ } */
+
+ @Override
+ public final FBObject getFBObject(int bufferName) {
+ return ((GLFBODrawableImpl)drawable).getFBObject(bufferName);
+ }
+
+ @Override
+ public final FBObject.TextureAttachment getTextureBuffer(int bufferName) {
+ return ((GLFBODrawableImpl)drawable).getTextureBuffer(bufferName);
+ }
+
+ @Override
+ public void resetSize(GL gl) throws GLException {
+ ((GLFBODrawableImpl)drawable).resetSize(gl);
+ }
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index 0f4f7f8e2..c32957b86 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.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,283 +29,77 @@
* 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 com.jogamp.common.util.locks.LockFactory;
-import com.jogamp.common.util.locks.RecursiveLock;
-
-import javax.media.nativewindow.AbstractGraphicsDevice;
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLAnimatorControl;
-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.GLException;
import javax.media.opengl.GLPbuffer;
-import javax.media.opengl.GLProfile;
-import javax.media.opengl.GLRunnable;
-/** Platform-independent class exposing pbuffer functionality to
- applications. This class is not exposed in the public API as it
- would probably add no value; however it implements the GLDrawable
- interface so can be interacted with via its display() method. */
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
-public class GLPbufferImpl implements GLPbuffer {
- private GLDrawableImpl pbufferDrawable;
- private GLContextImpl context;
- private GLDrawableHelper drawableHelper = new GLDrawableHelper();
- private int floatMode;
- private int additionalCtxCreationFlags = 0;
+@SuppressWarnings("deprecation")
+public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
- public GLPbufferImpl(GLDrawableImpl pbufferDrawable,
- GLContext parentContext) {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)
- pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
- if(caps.isOnscreen()) {
- if(caps.isPBuffer()) {
- throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable);
- }
- throw new IllegalArgumentException("Error: Given drawable is Onscreen: "+pbufferDrawable);
- } else {
- if(!caps.isPBuffer()) {
- throw new IllegalArgumentException("Error: Given drawable is not Pbuffer: "+pbufferDrawable);
- }
- }
- this.pbufferDrawable = pbufferDrawable;
- context = (GLContextImpl) pbufferDrawable.createContext(parentContext);
+ public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) {
+ super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext
}
- public GLContext createContext(GLContext shareWith) {
- return pbufferDrawable.createContext(shareWith);
- }
+ //
+ // pbuffer specifics
+ //
- public void setRealized(boolean realized) {
- }
+ //
+ // GLDrawable delegation
+ //
- public boolean isRealized() {
- return true;
+ @Override
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
}
- public void destroy() {
- if(pbufferDrawable.isRealized()) {
- final AbstractGraphicsDevice adevice = pbufferDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice();
-
- if (null != context && context.isCreated()) {
- try {
- drawableHelper.disposeGL(GLPbufferImpl.this, pbufferDrawable, context, null);
- } catch (GLException gle) {
- gle.printStackTrace();
- }
- context = null;
- // drawableHelper.reset();
- }
- pbufferDrawable.destroy();
- pbufferDrawable = null;
-
- if(null != adevice) {
- adevice.close();
- }
- }
- }
+ //
+ // GLAutoDrawable completion
+ //
+ private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
- public void setSize(int width, int height) {
- // FIXME
- throw new GLException("Not yet implemented");
- }
+ @Override
+ protected final RecursiveLock getLock() { return lock; }
- public NativeSurface getNativeSurface() {
- return pbufferDrawable.getNativeSurface();
+ @Override
+ public final Object getUpstreamWidget() {
+ return null;
}
- public long getHandle() {
- return pbufferDrawable.getHandle();
+ @Override
+ public void destroy() {
+ defaultDestroy();
}
+ @Override
public GLDrawableFactory getFactory() {
- return pbufferDrawable.getFactory();
- }
-
- public int getWidth() {
- return pbufferDrawable.getWidth();
- }
-
- public int getHeight() {
- return pbufferDrawable.getHeight();
- }
-
- public void display() {
- invokeGL(displayAction);
- }
-
- public void repaint() {
- display();
- }
-
- public void addGLEventListener(GLEventListener listener) {
- drawableHelper.addGLEventListener(listener);
- }
-
- public void addGLEventListener(int index, GLEventListener listener) {
- drawableHelper.addGLEventListener(index, listener);
- }
-
- public void removeGLEventListener(GLEventListener listener) {
- drawableHelper.removeGLEventListener(listener);
- }
-
- public void setAnimator(GLAnimatorControl animatorControl) {
- drawableHelper.setAnimator(animatorControl);
- }
-
- public GLAnimatorControl getAnimator() {
- return drawableHelper.getAnimator();
- }
-
- public void invoke(boolean wait, GLRunnable glRunnable) {
- drawableHelper.invoke(this, wait, glRunnable);
- }
-
- public void setContext(GLContext ctx) {
- context=(GLContextImpl)ctx;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
- }
+ return drawable.getFactory();
}
- public GLContext getContext() {
- return context;
- }
-
- public GLDrawable getDrawable() {
- return pbufferDrawable;
- }
-
- public GL getGL() {
- return getContext().getGL();
- }
-
- public GL setGL(GL gl) {
- return getContext().setGL(gl);
- }
-
- public void setAutoSwapBufferMode(boolean onOrOff) {
- drawableHelper.setAutoSwapBufferMode(onOrOff);
- }
-
- public boolean getAutoSwapBufferMode() {
- return drawableHelper.getAutoSwapBufferMode();
- }
-
- public void swapBuffers() {
- invokeGL(swapBuffersAction);
- }
-
- public void setContextCreationFlags(int flags) {
- additionalCtxCreationFlags = flags;
- if(null != context) {
- context.setContextCreationFlags(additionalCtxCreationFlags);
- }
- }
-
- public int getContextCreationFlags() {
- return additionalCtxCreationFlags;
- }
-
- 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();
- }
-
- 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();
- }
-
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- if (pbufferDrawable == null)
- return null;
-
- return pbufferDrawable.getChosenGLCapabilities();
- }
-
- public GLCapabilitiesImmutable getRequestedGLCapabilities() {
- if (pbufferDrawable == null)
- return null;
-
- return pbufferDrawable.getRequestedGLCapabilities();
- }
-
- public GLProfile getGLProfile() {
- if (pbufferDrawable == null)
- return null;
-
- return pbufferDrawable.getGLProfile();
- }
-
- private RecursiveLock recurLock = LockFactory.createRecursiveLock();
-
- public int lockSurface() throws GLException {
- recurLock.lock();
- return NativeSurface.LOCK_SUCCESS;
- }
-
- public void unlockSurface() {
- recurLock.unlock();
- }
-
- public boolean isSurfaceLocked() {
- return recurLock.isLocked();
- }
-
- public int getFloatingPointMode() {
- if (floatMode == 0) {
- throw new GLException("Pbuffer not initialized, or floating-point support not requested");
- }
- return floatMode;
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- private void invokeGL(Runnable invokeGLAction) {
- drawableHelper.invokeGL(pbufferDrawable, context, invokeGLAction, initAction);
- }
-
-
- class InitAction implements Runnable {
- public void run() {
- floatMode = context.getFloatingPointMode();
- drawableHelper.init(GLPbufferImpl.this);
- }
- }
- private InitAction initAction = new InitAction();
-
- class DisplayAction implements Runnable {
- public void run() {
- drawableHelper.display(GLPbufferImpl.this);
- }
- }
- private DisplayAction displayAction = new DisplayAction();
-
- class SwapBuffersAction implements Runnable {
- public void run() {
- pbufferDrawable.swapBuffers();
+ @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, defaultInitAction);
+ }
+ } finally {
+ _lock.unlock();
}
}
- private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
}
diff --git a/src/jogl/classes/jogamp/opengl/GLRunnableTask.java b/src/jogl/classes/jogamp/opengl/GLRunnableTask.java
index 448f68423..6de92f533 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;
@@ -39,7 +39,8 @@ public class GLRunnableTask implements GLRunnable {
GLRunnable runnable;
Object notifyObject;
boolean catchExceptions;
- boolean isExecuted;
+ volatile boolean isExecuted;
+ volatile boolean isFlushed;
Throwable runnableException;
@@ -48,8 +49,10 @@ public class GLRunnableTask implements GLRunnable {
this.notifyObject = notifyObject ;
this.catchExceptions = catchExceptions;
isExecuted = false;
+ isFlushed = false;
}
+ @Override
public boolean run(GLAutoDrawable drawable) {
boolean res = true;
if(null == notifyObject) {
@@ -85,7 +88,40 @@ public class GLRunnableTask implements GLRunnable {
return res;
}
+ /**
+ * Simply flush this task and notify a waiting executor.
+ * The executor which might have been blocked until notified
+ * will be unblocked and the task removed from the queue.
+ *
+ * @see #isFlushed()
+ * @see #isInQueue()
+ */
+ public void flush() {
+ if(!isExecuted() && null != notifyObject) {
+ synchronized (notifyObject) {
+ isFlushed=true;
+ 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..0e451741c 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;
/** avoid rehash of static size pixel state map */
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 {
/**
* Empty pixel-store state
- */
+ */
private IntIntHashMap pixelStateMap;
-
+
/**
* set (client) pixel-store state, deep copy
- */
+ */
private final void setPixelStateMap(IntIntHashMap pixelStateMap) {
this.pixelStateMap = (IntIntHashMap) pixelStateMap.clone();
}
-
+
/**
* get (client) pixel-store state, return reference
- */
+ */
private 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;
+ 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) {
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) {
if(enabled) {
- int value = pixelStateMap.get(pname);
+ final int value = pixelStateMap.get(pname);
if(0xFFFFFFFF != value) {
params.put(params.position(), value);
return true;
@@ -157,7 +158,7 @@ public class GLStateTracker {
throw new GLException("stack contains no elements");
}
SavedState state = stack.remove(stack.size()-1); // pop
-
+
if(null==state) {
throw new GLException("null stack element (remaining stack size "+stack.size()+")");
}
@@ -165,7 +166,7 @@ public class GLStateTracker {
if ( null != state.getPixelStateMap() ) {
// use pulled client pixel-store state from stack
pixelStateMap = state.getPixelStateMap();
- } // else: empty-slot, not pushed by GL_CLIENT_PIXEL_STORE_BIT
+ } // else: empty-slot, not pushed by GL_CLIENT_PIXEL_STORE_BIT
}
}
@@ -176,20 +177,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..431c1a387 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(int[] val, int strEnd, short state, String versionString, 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(String versionString) {
+ 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 = VersionNumberString.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 (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(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..100b46a5e 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>
@@ -149,7 +149,7 @@ public class GLWorkerThread {
}
}
- public static void invoke(boolean wait, Runnable runnable)
+ public static void invoke(boolean wait, Runnable runnable)
throws InvocationTargetException, InterruptedException {
if(wait) {
invokeAndWait(runnable);
@@ -157,7 +157,7 @@ public class GLWorkerThread {
invokeLater(runnable);
}
}
-
+
public static void invokeAndWait(Runnable runnable)
throws InvocationTargetException, InterruptedException {
if (!started) {
@@ -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) {
@@ -246,7 +245,7 @@ public class GLWorkerThread {
break;
}
}
-
+
if (shouldTerminate) {
lock.notifyAll();
thread = null;
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..a64a2f5cd 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,7 +57,7 @@ public class ListenerSyncedImplStub<E> {
public synchronized final int size() {
return listeners.size();
}
-
+
public synchronized final void addListener(E listener) {
addListener(-1, listener);
}
@@ -68,12 +68,12 @@ public class ListenerSyncedImplStub<E> {
}
listeners.add(index, listener);
}
-
+
public synchronized final void removeListener(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
index 292700701..6ebefc517 100644
--- a/src/jogl/classes/jogamp/opengl/MemoryObject.java
+++ b/src/jogl/classes/jogamp/opengl/MemoryObject.java
@@ -31,19 +31,22 @@ package jogamp.opengl;
import java.nio.ByteBuffer;
import java.util.HashMap;
+import javax.media.opengl.GLBufferStorage;
+
+import com.jogamp.common.util.HashUtil;
+
/**
- *
+ * @deprecated No more used for GL buffer storage tracking, see {@link GLBufferStorage} and {@link GLBufferObjectTracker}.
*/
public class MemoryObject {
- private long addr;
- private long size;
- private int hash32;
+ private final long addr;
+ private final long size;
+ private final int hash;
private ByteBuffer buffer=null;
-
public MemoryObject(long addr, long size) {
this.addr = addr;
this.size = size;
- this.hash32 = getHash32(addr, size);
+ this.hash = HashUtil.getAddrSizeHash32_EqualDist(addr, size);
}
public void setBuffer(ByteBuffer buffer) {
@@ -55,68 +58,46 @@ public class MemoryObject {
}
/**
- * @return the 32bit hash value generated via {@link #getHash32(long, long)}
+ * @return the 32bit hash value generated via {@link HashUtil#getAddrSizeHash32_EqualDist(long, long)}.
*/
+ @Override
public int hashCode() {
- return hash32;
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "MemoryObject[addr 0x"+Long.toHexString(addr)+", size 0x"+Long.toHexString(size)+", hash32: 0x"+Integer.toHexString(hash)+"]";
}
/**
* 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;
+ final 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)
+ final MemoryObject obj1 = map.get(obj0); // get identity (fast)
if(null == obj1) {
map.put(obj0, obj0);
- obj1 = obj0;
+ return obj0;
+ } else {
+ return obj1;
}
- 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..d4fd1c935 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,7 +108,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.
@@ -122,21 +122,21 @@ 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
@@ -153,62 +153,36 @@ public class ProjectFloat {
private final float[] out = new float[4];
// Buffer-based implementation
- private FloatBuffer matrixBuf;
- private FloatBuffer tempInvertMatrixBuf;
-
- private FloatBuffer inBuf;
- private FloatBuffer outBuf;
+ private FloatBuffer matrixBuf; // 4x4
- private FloatBuffer forwardBuf;
- private FloatBuffer sideBuf;
- private FloatBuffer upBuf;
+ private final float[] forward = new float[3]; // 3
+ private final float[] side = new float[3]; // 3
+ private final float[] up = new float[3]; // 3
public ProjectFloat() {
- this(false);
+ this(true);
}
-
+
public ProjectFloat(boolean useBackingArray) {
- this(useBackingArray ? null : Buffers.newDirectByteBuffer(getRequiredFloatBufferSize() * Buffers.SIZEOF_FLOAT),
- useBackingArray ? new float[getRequiredFloatBufferSize()] : null,
+ 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.
+ * 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 ProjectFloat(Buffer floatBuffer, float[] floatArray, int floatOffset) {
+ matrixBuf = Buffers.slice2Float(floatBuffer, floatArray, floatOffset, 16);
}
public void destroy() {
matrixBuf = null;
- tempInvertMatrixBuf = null;
- inBuf = null;
- outBuf = null;
- forwardBuf = null;
- sideBuf = null;
- upBuf = null;
}
/**
@@ -221,7 +195,7 @@ public class ProjectFloat {
public boolean gluInvertMatrixf(float[] src, int srcOffset, float[] inverse, int inverseOffset) {
int i, j, k, swap;
float t;
- float[][] temp = tempInvertMatrix;
+ final float[][] temp = tempInvertMatrix;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
@@ -285,21 +259,21 @@ public class ProjectFloat {
/**
* @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();
+ final int srcPos = src.position();
+ final int invPos = inverse.position();
- FloatBuffer temp = tempInvertMatrixBuf;
+ final float[][] temp = tempInvertMatrix;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
- temp.put(i*4+j, src.get(i*4+j + srcPos));
+ temp[i][j] = src.get(i*4+j + srcPos);
}
}
FloatUtil.makeIdentityf(inverse);
@@ -310,7 +284,7 @@ public class ProjectFloat {
//
swap = i;
for (j = i + 1; j < 4; j++) {
- if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) {
+ if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) {
swap = j;
}
}
@@ -320,9 +294,9 @@ public class ProjectFloat {
// 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 = temp[i][k];
+ temp[i][k] = temp[swap][k];
+ temp[swap][k] = t;
t = inverse.get(i*4+k + invPos);
inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos));
@@ -330,7 +304,7 @@ public class ProjectFloat {
}
}
- if (temp.get(i*4+i) == 0) {
+ 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.
@@ -338,17 +312,19 @@ public class ProjectFloat {
return false;
}
- t = temp.get(i*4+i);
+ t = temp[i][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);
+ temp[i][k] /= t;
+ final int z = i*4+k + invPos;
+ inverse.put(z, inverse.get(z) / t);
}
for (j = 0; j < 4; j++) {
if (j != i) {
- t = temp.get(j*4+i);
+ t = temp[j][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);
+ temp[j][k] -= temp[i][k] * t;
+ final int z = j*4+k + invPos;
+ inverse.put(z, inverse.get(z) - inverse.get(i*4+k + invPos) * t);
}
}
}
@@ -359,7 +335,7 @@ public class ProjectFloat {
/**
* Method gluOrtho2D.
- *
+ *
* @param left
* @param right
* @param bottom
@@ -371,15 +347,15 @@ public class ProjectFloat {
/**
* Method gluPerspective.
- *
+ *
* @param fovy
* @param aspect
* @param zNear
* @param zFar
*/
public void gluPerspective(GLMatrixFunc gl, float fovy, float aspect, float zNear, float zFar) {
+ final float radians = fovy / 2 * (float) Math.PI / 180;
float sine, cotangent, deltaZ;
- float radians = fovy / 2 * (float) Math.PI / 180;
deltaZ = zFar - zNear;
sine = (float) Math.sin(radians);
@@ -391,20 +367,20 @@ public class ProjectFloat {
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);
+ final int mPos = matrixBuf.position();
+ matrixBuf.put(0 * 4 + 0 + mPos, cotangent / aspect);
+ matrixBuf.put(1 * 4 + 1 + mPos, cotangent);
+ matrixBuf.put(2 * 4 + 2 + mPos, - (zFar + zNear) / deltaZ);
+ matrixBuf.put(2 * 4 + 3 + mPos, -1);
+ matrixBuf.put(3 * 4 + 2 + mPos, -2 * zNear * zFar / deltaZ);
+ matrixBuf.put(3 * 4 + 3 + mPos, 0);
gl.glMultMatrixf(matrixBuf);
}
/**
* Method gluLookAt
- *
+ *
* @param eyex
* @param eyey
* @param eyez
@@ -419,17 +395,17 @@ public class ProjectFloat {
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;
+ final float[] forward = this.forward;
+ final float[] side = this.side;
+ final float[] up = this.up;
- forward.put(0, centerx - eyex);
- forward.put(1, centery - eyey);
- forward.put(2, centerz - eyez);
+ forward[0] = centerx - eyex;
+ forward[1] = centery - eyey;
+ forward[2] = centerz - eyez;
- up.put(0, upx);
- up.put(1, upy);
- up.put(2, upz);
+ up[0] = upx;
+ up[1] = upy;
+ up[2] = upz;
FloatUtil.normalize(forward);
@@ -441,25 +417,26 @@ public class ProjectFloat {
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));
+ final int mPos = matrixBuf.position();
+ matrixBuf.put(0 * 4 + 0 + mPos, side[0]);
+ matrixBuf.put(1 * 4 + 0 + mPos, side[1]);
+ matrixBuf.put(2 * 4 + 0 + mPos, side[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 + 1 + mPos, up[0]);
+ matrixBuf.put(1 * 4 + 1 + mPos, up[1]);
+ matrixBuf.put(2 * 4 + 1 + mPos, up[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));
+ matrixBuf.put(0 * 4 + 2 + mPos, -forward[0]);
+ matrixBuf.put(1 * 4 + 2 + mPos, -forward[1]);
+ matrixBuf.put(2 * 4 + 2 + mPos, -forward[2]);
gl.glMultMatrixf(matrixBuf);
gl.glTranslatef(-eyex, -eyey, -eyez);
}
/**
- * Method gluProject
- *
+ * Map object coordinates to window coordinates.
+ *
* @param objx
* @param objy
* @param objz
@@ -467,7 +444,7 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
public boolean gluProject(float objx, float objy, float objz,
@@ -476,16 +453,16 @@ public class ProjectFloat {
int[] viewport, int viewport_offset,
float[] win_pos, int win_pos_offset ) {
- float[] in = this.in;
- float[] out = this.out;
+ final float[] in = this.in;
+ final float[] out = this.out;
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.multMatrixVecf(modelMatrix, modelMatrix_offset, in, 0, out, 0);
+ FloatUtil.multMatrixVecf(projMatrix, projMatrix_offset, out, 0, in, 0);
if (in[3] == 0.0f) {
return false;
@@ -506,45 +483,48 @@ public class ProjectFloat {
return true;
}
+ /**
+ * Map object coordinates to window coordinates.
+ */
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;
+ final float[] in = this.in;
+ final float[] out = this.out;
- 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);
- 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
- 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);
+ win_pos[0+win_pos_offset] = in[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset];
+ win_pos[1+win_pos_offset] = in[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset];
+ win_pos[2+win_pos_offset] = in[2];
return true;
}
-
+
/**
- * Method gluProject
- *
+ * Map object coordinates to window coordinates.
+ *
* @param objx
* @param objy
* @param objz
@@ -552,7 +532,7 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
public boolean gluProject(float objx, float objy, float objz,
@@ -561,42 +541,42 @@ public class ProjectFloat {
IntBuffer viewport,
FloatBuffer win_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
+ final float[] in = this.in;
+ final float[] out = this.out;
- 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);
- 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.
+ *
* @param winx
* @param winy
* @param winz
@@ -604,7 +584,7 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject(float winx, float winy, float winz,
@@ -612,8 +592,8 @@ public class ProjectFloat {
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;
+ final float[] in = this.in;
+ final float[] out = this.out;
FloatUtil.multMatrixf(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, matrix, 0);
@@ -651,13 +631,27 @@ public class ProjectFloat {
}
+ /**
+ * Map window coordinates to object coordinates.
+ *
+ * @param winx
+ * @param winy
+ * @param winz
+ * @param modelMatrix
+ * @param projMatrix
+ * @param viewport
+ * @param viewport_offset
+ * @param obj_pos
+ * @param obj_pos_offset
+ * @return
+ */
public boolean gluUnProject(float winx, float winy, float winz,
- FloatBuffer modelMatrix,
+ FloatBuffer modelMatrix,
FloatBuffer projMatrix,
int[] viewport, int viewport_offset,
float[] obj_pos, int obj_pos_offset) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
+ final float[] in = this.in;
+ final float[] out = this.out;
FloatUtil.multMatrixf(projMatrix, modelMatrix, matrixBuf);
@@ -665,38 +659,38 @@ public class ProjectFloat {
return false;
}
- in.put(0, winx);
- in.put(1, winy);
- in.put(2, winz);
- in.put(3, 1.0f);
+ in[0] = winx;
+ in[1] = winy;
+ in[2] = winz;
+ in[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]);
-
+ in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
+ in[1] = (in[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);
+ in[0] = in[0] * 2 - 1;
+ in[1] = in[1] * 2 - 1;
+ in[2] = in[2] * 2 - 1;
FloatUtil.multMatrixVecf(matrixBuf, in, out);
- if (out.get(3) == 0.0f) {
+ if (out[3] == 0.0) {
return false;
}
- out.put(3, 1.0f / out.get(3));
+ out[3] = 1.0f / out[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);
+ 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];
return true;
}
-
+
/**
- * Method gluUnproject
- *
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
@@ -704,16 +698,16 @@ public class ProjectFloat {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject(float winx, float winy, float winz,
- FloatBuffer modelMatrix,
+ FloatBuffer modelMatrix,
FloatBuffer projMatrix,
IntBuffer viewport,
FloatBuffer obj_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
+ final float[] in = this.in;
+ final float[] out = this.out;
FloatUtil.multMatrixf(projMatrix, modelMatrix, matrixBuf);
@@ -721,41 +715,41 @@ public class ProjectFloat {
return false;
}
- in.put(0, winx);
- in.put(1, winy);
- in.put(2, winz);
- in.put(3, 1.0f);
+ in[0] = winx;
+ in[1] = winy;
+ in[2] = winz;
+ in[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));
+ final int vPos = viewport.position();
+ final int oPos = obj_pos.position();
+ in[0] = (in[0] - viewport.get(0+vPos)) / viewport.get(2+vPos);
+ in[1] = (in[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);
+ in[0] = in[0] * 2 - 1;
+ in[1] = in[1] * 2 - 1;
+ in[2] = in[2] * 2 - 1;
FloatUtil.multMatrixVecf(matrixBuf, in, out);
- if (out.get(3) == 0.0f) {
+ if (out[3] == 0.0) {
return false;
}
- out.put(3, 1.0f / out.get(3));
+ out[3] = 1.0f / out[3];
- 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, out[0] * out[3]);
+ obj_pos.put(1+oPos, out[1] * out[3]);
+ obj_pos.put(2+oPos, out[2] * out[3]);
return true;
}
/**
- * Method gluUnproject4
- *
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
@@ -766,7 +760,7 @@ public class ProjectFloat {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject4(float winx,
@@ -783,8 +777,8 @@ public class ProjectFloat {
float far,
float[] obj_pos,
int obj_pos_offset ) {
- float[] in = this.in;
- float[] out = this.out;
+ final float[] in = this.in;
+ final float[] out = this.out;
FloatUtil.multMatrixf(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, matrix, 0);
@@ -808,8 +802,9 @@ public class ProjectFloat {
FloatUtil.multMatrixVecf(matrix, in, out);
- if (out[3] == 0.0f)
+ if (out[3] == 0.0f) {
return false;
+ }
obj_pos[0+obj_pos_offset] = out[0];
obj_pos[1+obj_pos_offset] = out[1];
@@ -819,8 +814,8 @@ public class ProjectFloat {
}
/**
- * Method gluUnproject4
- *
+ * Map window coordinates to object coordinates.
+ *
* @param winx
* @param winy
* @param winz
@@ -831,7 +826,7 @@ public class ProjectFloat {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject4(float winx,
@@ -844,47 +839,48 @@ public class ProjectFloat {
float near,
float far,
FloatBuffer obj_pos) {
- FloatBuffer in = this.inBuf;
- FloatBuffer out = this.outBuf;
+ final float[] in = this.in;
+ final float[] out = this.out;
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, clipw);
+ in[0] = winx;
+ in[1] = winy;
+ in[2] = winz;
+ in[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();
+ in[0] = (in[0] - viewport.get(0+vPos)) / viewport.get(2+vPos);
+ in[1] = (in[1] - viewport.get(1+vPos)) / viewport.get(3+vPos);
+ in[2] = (in[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);
+ in[0] = in[0] * 2 - 1;
+ in[1] = in[1] * 2 - 1;
+ in[2] = in[2] * 2 - 1;
FloatUtil.multMatrixVecf(matrixBuf, in, out);
- if (out.get(3) == 0.0f)
+ if (out[3] == 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, out[0]);
+ obj_pos.put(1+oPos, out[1]);
+ obj_pos.put(2+oPos, out[2]);
+ obj_pos.put(3+oPos, out[3]);
return true;
}
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
@@ -902,7 +898,7 @@ public class ProjectFloat {
}
/* 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);
@@ -911,7 +907,7 @@ public class ProjectFloat {
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
index 0528d3060..283ecdb9d 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,106 +83,115 @@ 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(String connection) { // synchronized call
+ return devicesTried.contains(connection);
}
- private void addDeviceTried(String connection) {
- synchronized (devicesTried) {
- devicesTried.add(connection);
- }
+ private void addDeviceTried(String connection) { // synchronized call
+ devicesTried.add(connection);
}
- private void removeDeviceTried(String connection) {
- synchronized (devicesTried) {
- devicesTried.remove(connection);
- }
+ private void removeDeviceTried(String connection) { // synchronized call
+ devicesTried.remove(connection);
}
public SharedResourceRunner(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 (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 (InterruptedException ex) { }
}
}
}
}
}
-
+
public SharedResourceRunner.Resource getOrCreateShared(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());
+ }
+ }
}
}
}
@@ -170,16 +201,18 @@ public class SharedResourceRunner implements Runnable {
public SharedResourceRunner.Resource releaseShared(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());
+ }
}
}
}
@@ -187,18 +220,17 @@ public class SharedResourceRunner implements Runnable {
}
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);
- }
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 (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 (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 (InterruptedException ex) {
shouldRelease = true;
if(DEBUG) {
- System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+Thread.currentThread().getName());
+ System.err.println("SharedResourceRunner.run(): INTERRUPTED - "+threadName);
ex.printStackTrace();
}
}
@@ -260,9 +294,7 @@ public class SharedResourceRunner implements Runnable {
try {
sr = impl.createSharedResource(initConnection);
} catch (Exception e) {
- if(DEBUG) {
- e.printStackTrace();
- }
+ e.printStackTrace();
}
if (null != sr) {
impl.mapPut(initConnection, sr);
@@ -280,7 +312,7 @@ public class SharedResourceRunner implements Runnable {
} catch (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();
- }
+ private void releaseSharedResources() { // synchronized call
+ devicesTried.clear();
Collection<Resource> sharedResources = impl.mapValues();
for (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());
+ System.err.println("Catched Exception on thread "+getThreadName());
t.printStackTrace();
}
}
impl.clear();
}
+
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
}
diff --git a/src/jogl/classes/jogamp/opengl/ThreadingImpl.java b/src/jogl/classes/jogamp/opengl/ThreadingImpl.java
index 61a47675f..bf700d970 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;
@@ -49,14 +49,14 @@ import com.jogamp.common.util.ReflectionUtil;
public class ThreadingImpl {
public enum Mode {
- MT(0), ST_AWT(1), ST_WORKER(2);
-
+ 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");
@@ -68,10 +68,11 @@ 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;
{
@@ -89,13 +90,12 @@ public class ThreadingImpl {
// problems.
hasAWT = GLProfile.isAWTAvailable();
- String osType = NativeWindowFactory.getNativeWindowType(false);
- _isX11 = NativeWindowFactory.TYPE_X11.equals(osType);
+ _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")) {
@@ -114,7 +114,7 @@ public class ThreadingImpl {
throw new RuntimeException("Unsupported value for property jogl.1thread: "+singleThreadProp+", should be [true/auto, worker, awt or false]");
}
}
-
+
ToolkitThreadingPlugin threadingPlugin=null;
if(hasAWT) {
// try to fetch the AWTThreadingPlugin
@@ -140,9 +140,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
@@ -152,7 +152,7 @@ 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()) {
@@ -184,7 +184,7 @@ public class ThreadingImpl {
throw new InternalError("Illegal single-threading mode " + mode);
}
}
-
+
public static final boolean isToolkitThread() throws GLException {
if(null!=threadingPlugin) {
return threadingPlugin.isToolkitThread();
@@ -216,7 +216,7 @@ public class ThreadingImpl {
throw new InternalError("Illegal single-threading mode " + mode);
}
}
-
+
public static final void invokeOnWorkerThread(boolean wait, Runnable r) throws GLException {
GLWorkerThread.start(); // singleton start via volatile-dbl-checked-locking
try {
@@ -225,6 +225,6 @@ public class ThreadingImpl {
throw new GLException(e.getTargetException());
} catch (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..25a0bc15d 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,10 +28,17 @@
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.android.StaticContext;
@@ -39,7 +46,9 @@ 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,47 +69,63 @@ 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(Platform.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(float rate) {
+ // FIXME
return false;
}
@Override
- protected boolean startImpl() {
- if(null != mp) {
+ protected final boolean setAudioVolumeImpl(float v) {
+ if(null != mp) {
try {
- mp.start();
+ mp.setVolume(v, v);
return true;
} catch (IllegalStateException ise) {
if(DEBUG) {
@@ -107,11 +137,24 @@ 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 (IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ } else if( null != cam ) {
+ try {
+ if( sTexFrameAttached ) {
+ cam.startPreview();
+ }
return true;
} catch (IllegalStateException ise) {
if(DEBUG) {
@@ -123,11 +166,21 @@ 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) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ } else if( null != cam ) {
+ wakeUp(false);
+ try {
+ cam.stopPreview();
return true;
} catch (IllegalStateException ise) {
if(DEBUG) {
@@ -137,9 +190,9 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
}
return false;
}
-
+
@Override
- protected int seekImpl(int msec) {
+ protected final int seekImpl(int msec) {
if(null != mp) {
mp.seekTo(msec);
return mp.getCurrentPosition();
@@ -147,40 +200,6 @@ 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) {
synchronized(updateSurfaceLock) {
if(newFrame) {
@@ -189,29 +208,80 @@ 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(GL gl) {
if(null != mp) {
wakeUp(false);
+ try {
+ mp.stop();
+ } catch (IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
mp.release();
mp = null;
}
+ if( null != cam ) {
+ wakeUp(false);
+ try {
+ cam.stopPreview();
+ } catch (IllegalStateException ise) {
+ if(DEBUG) {
+ ise.printStackTrace();
+ }
+ }
+ cam.release();
+ cam = null;
+ }
}
-
- SurfaceTexture stex = null;
-
+
+ public static class SurfaceTextureFrame extends TextureSequence.TextureFrame {
+ public SurfaceTextureFrame(Texture t, 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 == streamLoc ) {
+ return;
+ }
+ if( null == mp && null == cam ) {
+ if( null == cameraPath ) {
+ mp = new MediaPlayer();
+ } else {
+ int cameraId = 0;
+ try {
+ cameraId = Integer.valueOf(cameraPath);
+ } catch (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);
+ final Uri _uri = Uri.parse(streamLoc.toString());
+ mp.setDataSource(StaticContext.getContext(), _uri);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (SecurityException e) {
@@ -219,44 +289,206 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
} catch (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);
+ throw new IOException("MediaPlayer failed to process stream <"+streamLoc.toString()+">: "+ioe.getMessage(), ioe);
+ }
+ 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(mp.getVideoWidth(), mp.getVideoHeight(),
- 0, 0, 0,
- 0f, 0, mp.getDuration(),
- null, null);
+ 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(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(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(int desiredTextureCount) {
+ return TEXTURE_COUNT_MIN;
+ }
+
+ @Override
+ protected final int getNextTextureImpl(GL gl, 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 (IOException ioe) {
+ throw new RuntimeException("MediaPlayer failed to process stream <"+streamLoc.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 (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());
+ }
+ }
+ nextFrame.setPTS( pts );
+ }
+ return pts;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Creates only one single texture and duplicated content to 2 TextureFrames
+ * </p>
+ */
+ @Override
+ protected TextureFrame[] createTexFrames(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(GL gl, int texName) {
+ sTexFrameCount++;
+ if( 1 == sTexFrameCount ) {
+ singleSTexFrame = new SurfaceTextureFrame( createTexImageImpl(gl, texName, width, height), new SurfaceTexture(texName) );
+ }
+ return singleSTexFrame;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Destroys the single texture at last call.
+ * </p>
+ */
+ @Override
+ protected final void destroyTexFrame(GL gl, 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) {
wakeUp(true);
- AndroidGLMediaPlayerAPI14.this.newFrameAvailable();
- }
- };
+ }
+ };
+
+ private final OnCompletionListener onCompletionListener = new OnCompletionListener() {
+ @Override
+ public void onCompletion(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..72c9ac54b 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,6 +85,7 @@ public class AWTThreadingPlugin implements ToolkitThreadingPlugin {
}
}
+ @Override
public final void invokeOnOpenGLThread(boolean wait, Runnable r) throws GLException {
switch (ThreadingImpl.getMode()) {
case ST_AWT:
@@ -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);
}
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..1c1d2350a
--- /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(Graphics2D g2d) {
+ final RenderingHints rHints = g2d.getRenderingHints();
+ final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
+ int count = 0;
+ for(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(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(TileRenderer renderer, int componentCount, double scaleMatX, double scaleMatY, int numSamples, int tileWidth, int tileHeight, 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(boolean flipVertical, boolean originBottomLeft) {
+ this.flipVertical = flipVertical;
+ this.originBottomLeft = originBottomLeft;
+ }
+
+ private static Rectangle2D getClipBounds2D(Graphics2D g) {
+ final Shape shape = g.getClip();
+ return null != shape ? shape.getBounds2D() : null;
+ }
+ private static Rectangle2D clipNegative(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(Graphics2D g2d, int width, 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(GLAutoDrawable drawable) {}
+ @Override
+ public void dispose(GLAutoDrawable drawable) {}
+ @Override
+ public void display(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(GLAutoDrawable drawable, int x, int y, int width, int height) {}
+ };
+ static int _counter = 0;
+ final GLEventListener postTileGLEL = new GLEventListener() {
+ @Override
+ public void init(GLAutoDrawable drawable) {
+ }
+ @Override
+ public void dispose(GLAutoDrawable drawable) {}
+ @Override
+ public void display(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 (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 (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(GLAutoDrawable drawable, int x, int y, int width, int height) {}
+ };
+}
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java b/src/jogl/classes/jogamp/opengl/awt/AWTUtil.java
index e15e538c2..dc286ca59 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.
@@ -85,7 +85,7 @@ public class AWTUtil {
NativeWindowFactory.getAWTToolkitLock().lock();
}
} catch (Exception e) { j2dOk=false; }
- }
+ }
if(!j2dOk) {
NativeWindowFactory.getAWTToolkitLock().lock();
}
@@ -108,7 +108,7 @@ public class AWTUtil {
NativeWindowFactory.getAWTToolkitLock().unlock();
}
} catch (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..886cd9368 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.
*/
@@ -69,6 +69,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,6 +116,7 @@ public class Java2D {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
public Object run() {
if (DEBUG) {
System.err.println("Checking for Java2D/OpenGL support");
@@ -124,18 +126,36 @@ public class Java2D {
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 = Platform.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 {
@@ -152,99 +172,101 @@ 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 (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);
+ }
}
} catch (Exception e) {
catched = e;
@@ -252,6 +274,7 @@ public class Java2D {
System.err.println("Info: Disabling Java2D/JOGL integration");
}
isOGLPipelineActive = false;
+ isOGLPipelineResourceCompatible = false;
}
}
} catch (HeadlessException e) {
@@ -265,7 +288,7 @@ public class Java2D {
if(null != catched) {
catched.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 +299,10 @@ public class Java2D {
return isOGLPipelineActive;
}
+ public static boolean isOGLPipelineResourceCompatible() {
+ return isOGLPipelineResourceCompatible;
+ }
+
public static boolean isFBOEnabled() {
return fbObjectSupportInitialized;
}
@@ -291,7 +318,7 @@ public class Java2D {
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. */
@@ -330,7 +357,7 @@ public class Java2D {
false if the passed GraphicsConfiguration was not an OpenGL
GraphicsConfiguration. */
public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException {
- checkActive();
+ checkCompatible();
try {
AWTUtil.lockToolkit();
@@ -355,7 +382,7 @@ public class Java2D {
public static Rectangle getOGLViewport(Graphics g,
int componentWidth,
int componentHeight) {
- checkActive();
+ checkCompatible();
try {
return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g,
@@ -375,7 +402,7 @@ public class Java2D {
passed to a call to glScissor(). Should only be called from the
Queue Flusher Thread. */
public static Rectangle getOGLScissorBox(Graphics g) {
- checkActive();
+ checkCompatible();
try {
return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g});
@@ -393,7 +420,7 @@ public class Java2D {
created (and the old ones destroyed). Should only be called from
the Queue Flusher Thread.*/
public static Object getOGLSurfaceIdentifier(Graphics g) {
- checkActive();
+ checkCompatible();
try {
return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g});
@@ -408,7 +435,7 @@ public class Java2D {
object. This indicates, in particular, whether Java2D is
currently rendering into a pbuffer or FBO. */
public static int getOGLSurfaceType(Graphics g) {
- checkActive();
+ checkCompatible();
try {
// FIXME: fallback path for pre-b73 (?) Mustang builds -- remove
@@ -429,7 +456,7 @@ public class Java2D {
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();
+ checkCompatible();
if (getOGLTextureTypeMethod == null) {
return GL.GL_TEXTURE_2D;
@@ -483,7 +510,7 @@ public class Java2D {
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();
+ checkCompatible();
try {
return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, new Long(shareCtx) })).longValue();
@@ -497,7 +524,7 @@ public class Java2D {
/** (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();
+ checkCompatible();
try {
return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, new Long(ctx) })).booleanValue();
@@ -510,7 +537,7 @@ public class Java2D {
/** (Mac OS X-specific) Destroys the given OpenGL context. */
public static void destroyOGLContext(long ctx) {
- checkActive();
+ checkCompatible();
try {
destroyOGLContextMethod.invoke(null, new Object[] { new Long(ctx) });
@@ -527,12 +554,19 @@ 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>() {
+ @Override
public Integer run() {
try {
Class<?> utils = Class.forName("sun.java2d.opengl.OGLUtilities");
@@ -562,7 +596,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 +610,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..9173a38cb 100644
--- a/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
+++ b/src/jogl/classes/jogamp/opengl/awt/VersionApplet.java
@@ -42,7 +42,7 @@ public class VersionApplet extends Applet {
va.init();
frame.add(va, BorderLayout.CENTER);
frame.validate();
-
+
frame.setVisible(true);
va.start();
}
@@ -54,6 +54,7 @@ public class VersionApplet extends Applet {
this.f = f;
this.va = va;
}
+ @Override
public void windowClosing(WindowEvent ev) {
f.setVisible(false);
va.stop();
@@ -68,7 +69,7 @@ public class VersionApplet extends Applet {
if(null != canvas) { return; }
setEnabled(true);
-
+
GLProfile glp = GLProfile.getDefault();
GLCapabilities glcaps = new GLCapabilities(glp);
@@ -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();
@@ -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,6 +159,7 @@ public class VersionApplet extends Applet {
}
class GLInfo implements GLEventListener {
+ @Override
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
String s = JoglVersion.getGLInfo(gl, null).toString();
@@ -161,12 +167,15 @@ public class VersionApplet extends Applet {
tareaVersion.append(s);
}
+ @Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
}
+ @Override
public void display(GLAutoDrawable drawable) {
}
+ @Override
public void dispose(GLAutoDrawable drawable) {
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/DesktopES2DynamicLibraryBundleInfo.java
index cddd142e9..7b85c3e75 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>();
res.add("eglGetProcAddress");
return res;
}
+ @Override
public final long toolGetProcAddress(long toolGetProcAddressHandle, String funcName) {
return EGL.eglGetProcAddress(toolGetProcAddressHandle, funcName);
}
+ @Override
public final boolean useToolGetProcAdressFirst(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 f5f9f62c4..f89ded4f6 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.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,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.
*/
@@ -42,7 +42,9 @@ import java.util.Map;
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;
@@ -50,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;
@@ -68,14 +71,15 @@ public abstract class EGLContext extends GLContextImpl {
}
@Override
- protected void resetStates() {
+ protected void resetStates(boolean isInit) {
eglQueryStringInitialized = false;
eglQueryStringAvailable = false;
eglExtProcAddressTable = null;
// no inner state _eglExt = null;
- super.resetStates();
+ super.resetStates(isInit);
}
-
+
+ @Override
public Object getPlatformGLExtensions() {
return getEGLExt();
}
@@ -87,6 +91,7 @@ public abstract class EGLContext extends GLContextImpl {
return _eglExt;
}
+ @Override
public final ProcAddressTable getPlatformExtProcAddressTable() {
return eglExtProcAddressTable;
}
@@ -95,75 +100,80 @@ public abstract class EGLContext extends GLContextImpl {
return eglExtProcAddressTable;
}
+ @Override
protected Map<String, String> getFunctionNameMap() { return null; }
+ @Override
protected Map<String, String> getExtensionNameMap() { return null; }
+ @Override
public final boolean isGLReadDrawableAvailable() {
return true;
}
+ @Override
protected void makeCurrentImpl() throws GLException {
- if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) {
- throw new GLException("drawable not properly initialized, NO DISPLAY: "+drawable);
- }
if (EGL.eglGetCurrentContext() != contextHandle) {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- 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);
}
}
}
+ @Override
protected void releaseImpl() throws GLException {
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- 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()));
+ 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 " + toHexString(contextHandle) +
+ ": error code " + toHexString(EGL.eglGetError()));
}
}
+ @Override
protected void destroyImpl() throws GLException {
- if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), 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) {
return 0; // FIXME
}
+ @Override
protected void destroyContextARBImpl(long _context) {
- // FIXME
+ 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));
+ }
+ }
}
- protected boolean createImpl(GLContextImpl shareWith) throws GLException {
- long eglDisplay = ((EGLDrawable)drawable).getDisplay();
- EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration();
- GLProfile glProfile = drawable.getGLProfile();
- long eglConfig = config.getNativeConfig();
- long shareWithHandle = EGL.EGL_NO_CONTEXT;
-
- if (eglDisplay == 0) {
+ @Override
+ 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();
+ // 0 == EGL.EGL_NO_CONTEXT;
+
+ if ( 0 == eglDisplay ) {
throw new GLException("Error: attempted to create an OpenGL context without a display connection");
}
- if (eglConfig == 0) {
+ if ( 0 == eglConfig ) {
throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration");
}
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("Catched: eglBindAPI to ES failed , error "+toHexString(EGL.eglGetError()));
}
} catch (GLException glex) {
if (DEBUG) {
@@ -171,26 +181,29 @@ public abstract class EGLContext extends GLContextImpl {
}
}
- 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 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);
@@ -200,31 +213,32 @@ public abstract class EGLContext extends GLContextImpl {
}
if (DEBUG) {
System.err.println(getThreadName() + ": Created OpenGL context 0x" +
- Long.toHexString(contextHandle) +
+ Long.toHexString(contextHandle) +
",\n\twrite surface 0x" + Long.toHexString(drawable.getHandle()) +
",\n\tread surface 0x" + Long.toHexString(drawableRead.getHandle())+
",\n\t"+this+
",\n\tsharing with 0x" + Long.toHexString(shareWithHandle));
}
- if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(),
- drawable.getHandle(),
- drawableRead.getHandle(),
- contextHandle)) {
- throw new GLException("Error making context 0x" +
- Long.toHexString(contextHandle) + " current: error code " + EGL.eglGetError());
+ if (!EGL.eglMakeCurrent(eglDisplay, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ throw new GLException("Error making context " +
+ toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError()));
}
- int ctp = CTX_PROFILE_ES;
- int major;
- if(glProfile.usesNativeGLES2()) {
- ctp |= CTX_IMPL_ES2_COMPAT;
- major = 2;
- } else {
- major = 1;
+ 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;
}
- setGLFunctionAvailability(true, major, 0, ctp);
- return true;
}
+ @Override
protected final void updateGLXProcAddressTable() {
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
@@ -255,17 +269,16 @@ public abstract class EGLContext extends GLContextImpl {
}
}
}
-
+
+ @Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
- StringBuilder sb = new StringBuilder();
+ StringBuilder sb = new StringBuilder();
if (!eglQueryStringInitialized) {
- eglQueryStringAvailable =
- getDrawableImpl().getGLDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0;
+ eglQueryStringAvailable = getDrawableImpl().getGLDynamicLookupHelper().isFunctionAvailable("eglQueryString");
eglQueryStringInitialized = true;
}
if (eglQueryStringAvailable) {
- final String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(),
- EGL.EGL_EXTENSIONS);
+ final String ret = EGL.eglQueryString(drawable.getNativeSurface().getDisplayHandle(), EGL.EGL_EXTENSIONS);
if (DEBUG) {
System.err.println("EGL extensions: " + ret);
}
@@ -276,22 +289,63 @@ 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));
- }
+ if( hasRendererQuirk(GLRendererQuirks.NoSetSwapInterval) ) {
return false;
}
- return EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval);
+ return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval);
}
- public abstract void bindPbufferToTexture();
+ //
+ // Accessible ..
+ //
- public abstract void releasePbufferFromTexture();
+ /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) {
+ mapStaticGLVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions);
+ }
+ /* pp */ int getContextOptions() { return ctxOptions; }
+ /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) {
+ final GLProfile glp = caps.getGLProfile();
+ final int[] reqMajorCTP = new int[2];
+ GLContext.getRequestMajorAndCompat(glp, reqMajorCTP);
+ 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() ) {
+ reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT;
+ }
+ mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]);
+ }
+ /* pp */ static void mapStaticGLVersion(AbstractGraphicsDevice device, int major, int minor, int ctp) {
+ if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) {
+ // ES1, ES2, ES3, ..
+ mapStaticGLVersion(device, major /* reqMajor */, major, minor, ctp);
+ if( 3 == major ) {
+ // map ES2 -> ES3
+ mapStaticGLVersion(device, 2 /* reqMajor */, major, minor, ctp);
+ }
+ }
+ }
+ private static void mapStaticGLVersion(AbstractGraphicsDevice device, int reqMajor, int major, int minor, 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(int major, int minor, int ctp, String gl_version) {
+ return GLContext.getGLVersion(major, minor, ctp, gl_version);
+ }
+
+ protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ return GLContext.getAvailableGLVersionsSet(device);
+ }
+ protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) {
+ GLContext.setAvailableGLVersionsSet(device);
+ }
protected static String toHexString(int hex) {
return GLContext.toHexString(hex);
@@ -299,25 +353,23 @@ public abstract class EGLContext extends GLContextImpl {
protected static String toHexString(long hex) {
return GLContext.toHexString(hex);
}
-
+
//----------------------------------------------------------------------
// Currently unimplemented stuff
//
+ @Override
protected void copyImpl(GLContext source, int mask) throws GLException {
throw new GLException("Not yet implemented");
}
-
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- throw new GLException("Should not call this");
- }
-
- public boolean offscreenImageNeedsVerticalFlip() {
+ @Override
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
throw new GLException("Should not call this");
}
- public int getOffscreenContextPixelDataType() {
+ @Override
+ public final void glFreeMemoryNV(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 e09400c09..c5f76f667 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.
@@ -29,105 +29,310 @@
package jogamp.opengl.egl;
import java.nio.IntBuffer;
+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("EGL");
-
- 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) {
+ 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(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 || openEGLDisplays.size() > 0 ) {
+ System.err.println("EGLDisplayUtil.EGLDisplays: Shutdown (open: "+openEGLDisplays.size()+")");
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ if( openEGLDisplays.size() > 0) {
+ dumpOpenDisplayConnections();
+ }
+ }
+ return openEGLDisplays.size();
+ }
+
+ public static void dumpOpenDisplayConnections() {
+ System.err.println("EGLDisplayUtil: Open EGL Display Connections: "+openEGLDisplays.size());
+ int i=0;
+ for(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(boolean v) { useSingletonEGLDisplay = v; }
+
+ private static synchronized long eglGetDisplay(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;
}
-
- public static long eglGetDisplay(NativeSurface surface, boolean allowFallBackToDefault) {
- final long nDisplay;
- if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) {
- nDisplay = surface.getSurfaceHandle(); // don't even ask ..
- } else {
- nDisplay = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
+
+ /**
+ * @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)
+ */
+ private static synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
+ }
+ final EGLDisplayRef d = EGLDisplayRef.getOrCreateOpened(eglDisplay, major, minor);
+ if(DEBUG) {
+ System.err.println("EGLDisplayUtil.eglInitialize("+EGLContext.toHexString(eglDisplay)+" ...): "+d+" = "+(null != d)+", singletonEGLDisplay "+singletonEGLDisplay+" (use "+useSingletonEGLDisplay+")");
+ // Thread.dumpStack();
+ }
+ 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 major
+ * @param minor
+ * @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)
+ */
+ private static synchronized int eglGetDisplayAndInitialize(long nativeDisplayID, long[] eglDisplay, int[] eglErr, IntBuffer major, IntBuffer minor) {
+ eglDisplay[0] = EGL.EGL_NO_DISPLAY;
+ final long _eglDisplay = eglGetDisplay( nativeDisplayID );
+ if ( EGL.EGL_NO_DISPLAY == _eglDisplay ) {
+ eglErr[0] = EGL.eglGetError();
+ return EGL.EGL_BAD_DISPLAY;
}
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(nDisplay);
- if (eglDisplay == EGL.EGL_NO_DISPLAY && nDisplay != EGL.EGL_DEFAULT_DISPLAY && allowFallBackToDefault) {
+ 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
+ */
+ private static synchronized long eglGetDisplayAndInitialize(long[] nativeDisplayID) {
+ final long[] eglDisplay = new long[1];
+ final int[] eglError = new int[1];
+ int eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(nativeDisplayID[0], eglDisplay, eglError, null, null);
+ if( EGL.EGL_SUCCESS == eglRes ) {
+ return eglDisplay[0];
+ }
+ if( EGL.EGL_DEFAULT_DISPLAY != nativeDisplayID[0] ) { // fallback to DEGAULT_DISPLAY
if(DEBUG) {
- System.err.println("EGLDisplayUtil.eglGetDisplay(): Fall back to EGL_DEFAULT_DISPLAY");
+ System.err.println("EGLDisplayUtil.eglGetAndInitDisplay failed with native "+EGLContext.toHexString(nativeDisplayID[0])+", error "+EGLContext.toHexString(eglRes)+"/"+EGLContext.toHexString(eglError[0])+" - fallback!");
+ }
+ eglRes = EGLDisplayUtil.eglGetDisplayAndInitialize(EGL.EGL_DEFAULT_DISPLAY, eglDisplay, eglError, null, null);
+ if( EGL.EGL_SUCCESS == eglRes ) {
+ nativeDisplayID[0] = EGL.EGL_DEFAULT_DISPLAY;
+ return eglDisplay[0];
}
- eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
}
- return eglDisplay;
+ 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]));
}
-
- 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;
+
+ /**
+ * @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
+ */
+ private static synchronized boolean eglTerminate(long eglDisplay) {
+ if( EGL.EGL_NO_DISPLAY == eglDisplay) {
+ return false;
}
- eglDisplayCounter.put(eglDisplay, refCnt);
+ final boolean[] res = new boolean[1];
+ final EGLDisplayRef d = EGLDisplayRef.closeOpened(eglDisplay, res);
if(DEBUG) {
- System.err.println("EGL.eglInitialize(0x"+Long.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 synchronized boolean eglInitialize(long eglDisplay, IntBuffer major, IntBuffer minor) {
- 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;
+
+ private static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() {
+ @Override
+ public long eglGetAndInitDisplay(long[] nativeDisplayID) {
+ return eglGetDisplayAndInitialize(nativeDisplayID);
}
- eglDisplayCounter.put(eglDisplay, refCnt);
- if(DEBUG) {
- System.err.println("EGL.eglInitialize(0x"+Long.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+ @Override
+ public void eglTerminate(long eglDisplayHandle) {
+ EGLDisplayUtil.eglTerminate(eglDisplayHandle);
}
- return res;
+ };
+
+ /**
+ * 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 uninitialized {@link EGLGraphicsDevice}
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) {
+ return new EGLGraphicsDevice(nativeDisplayID, EGL.EGL_NO_DISPLAY, connection, unitID, eglLifecycleCallback);
}
-
- public static synchronized boolean eglTerminate(long eglDisplay) {
- 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);
+
+ /**
+ * 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 uninitialized EGLGraphicsDevice
+ */
+ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(NativeSurface surface) {
+ final long nativeDisplayID;
+ if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) {
+ nativeDisplayID = surface.getSurfaceHandle(); // don't even ask ..
} else {
- res = true;
- }
- if(0<=refCnt) { // no negative refCount
- eglDisplayCounter.put(eglDisplay, refCnt);
- }
- if(DEBUG) {
- System.err.println("EGL.eglTerminate(0x"+Long.toHexString(eglDisplay)+" ...): #"+refCnt+" = "+res);
+ nativeDisplayID = surface.getDisplayHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY
}
- return res;
+ final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice();
+ 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 b2119d728..f184edae3 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.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,229 +29,146 @@
* 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 jogamp.opengl.GLDynamicLookupHelper;
-import jogamp.opengl.GLDrawableImpl;
+import java.nio.IntBuffer;
-import javax.media.nativewindow.*;
-import javax.media.nativewindow.VisualIDHolder.VIDType;
-import javax.media.opengl.*;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindow;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
-import com.jogamp.nativewindow.egl.*;
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
public abstract class EGLDrawable extends GLDrawableImpl {
- protected boolean ownEGLDisplay = false; // for destruction
- protected boolean ownEGLSurface = false; // for destruction
- private EGLGraphicsConfiguration eglConfig;
- protected long eglDisplay;
- protected long eglSurface;
- protected EGLDrawable(EGLDrawableFactory factory,
- NativeSurface component) throws GLException {
+ protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException {
super(factory, component, false);
- eglSurface=EGL.EGL_NO_SURFACE;
- eglDisplay=0;
- }
-
- public long getDisplay() {
- return eglDisplay;
- }
-
- public long getHandle() {
- return eglSurface;
- }
-
- public EGLGraphicsConfiguration getGraphicsConfiguration() {
- return eglConfig;
- }
-
- public GLCapabilitiesImmutable getChosenGLCapabilities() {
- return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities();
}
+ @Override
public abstract GLContext createContext(GLContext shareWith);
- protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle);
+ protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle);
- private void recreateSurface() {
- // create a new EGLSurface ..
- if(EGL.EGL_NO_SURFACE!=eglSurface) {
- EGL.eglDestroySurface(eglDisplay, eglSurface);
- }
+ private final long createEGLSurface() {
+ final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
+ final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration();
+ final NativeSurface upstreamSurface = eglws.getUpstreamSurface();
- if(DEBUG) {
- System.err.println(getThreadName() + ": createSurface using eglDisplay "+toHexString(eglDisplay)+", "+eglConfig);
- }
+ long eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), upstreamSurface.getSurfaceHandle());
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), surface.getSurfaceHandle());
- int eglError0 = EGL.EGL_SUCCESS;
+ int eglError0;
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) {
- // Try window handle if available and differs (Windows HDC / HWND).
+ // Try window handle if available and differs (Windows HDC / HWND).
// ANGLE impl. required HWND on Windows.
- if(surface instanceof NativeWindow) {
- final NativeWindow nw = (NativeWindow) surface;
+ if(upstreamSurface instanceof NativeWindow) {
+ final NativeWindow nw = (NativeWindow) upstreamSurface;
if(nw.getWindowHandle() != nw.getSurfaceHandle()) {
if(DEBUG) {
System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle");
}
- eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), nw.getWindowHandle());
+ eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), nw.getWindowHandle());
if (EGL.EGL_NO_SURFACE == eglSurface) {
eglError0 = EGL.eglGetError();
}
}
}
}
+ } else {
+ eglError0 = EGL.EGL_SUCCESS;
}
if (EGL.EGL_NO_SURFACE == eglSurface) {
throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0));
}
-
if(DEBUG) {
- System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface));
+ System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface));
}
+ return eglSurface;
}
@Override
- protected final void updateHandle() {
- if(ownEGLSurface) {
- recreateSurface();
+ protected final void createHandle() {
+ final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
+ if(DEBUG) {
+ 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);
+ }
+ eglws.setSurfaceHandle( createEGLSurface() );
+ } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) {
+ throw new InternalError("Nil surface but claimed to be valid: "+eglws);
}
}
-
- protected void setRealizedImpl() {
- if (realized) {
- AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration();
- AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
- if(aDevice instanceof EGLGraphicsDevice) {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START");
- }
- // just fetch the data .. trust but verify ..
- eglDisplay = aDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice);
- }
- if(aConfig instanceof EGLGraphicsConfiguration) {
- eglConfig = (EGLGraphicsConfiguration) aConfig; // done ..
- if (null == eglConfig) {
- throw new GLException("Null EGLGraphicsConfiguration from "+aConfig);
- }
- int[] tmp = new int[1];
- if ( 0 != surface.getSurfaceHandle() &&
- EGL.eglQuerySurface(eglDisplay, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) {
- // surface holds static EGLSurface
- eglSurface = surface.getSurfaceHandle();
- if(DEBUG) {
- System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface));
- }
- } else {
- // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface();
- ownEGLSurface=true;
- }
- } else {
- throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig);
- }
- } else {
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START");
- }
- // create a new EGL config ..
- ownEGLDisplay=true;
- // EGLSurface is ours ..
- ownEGLSurface=true;
+ @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);
+ }
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglws.getGraphicsConfiguration().getScreen().getDevice();
+ if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ EGL.eglDestroySurface(eglDevice.getHandle(), eglws.getSurfaceHandle());
+ eglws.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+ }
+ }
- eglDisplay = EGLDisplayUtil.eglGetDisplay(surface, true);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL display: "+surface+", "+aDevice+", error "+toHexString(EGL.eglGetError()));
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error "+Integer.toHexString(EGL.eglGetError()));
- }
- EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
- AbstractGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex());
- final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
- if(aConfig instanceof EGLGraphicsConfiguration) {
- final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities();
- if(0 == capsChosen.getEGLConfig()) {
- // 'refresh' the native EGLConfig handle
- capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDisplay, capsChosen.getEGLConfigID()));
- if(0 == capsChosen.getEGLConfig()) {
- throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig);
- }
- }
- eglConfig = new EGLGraphicsConfiguration(s, capsChosen, capsRequested, null);
- if(DEBUG) {
- System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig);
- }
- } else {
- eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsRequested, capsRequested, null, s, aConfig.getVisualID(VIDType.NATIVE), false);
-
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s);
- } else if(DEBUG) {
- System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig);
- }
- }
- // subsequent updateHandle() will issue recreateSurface();
- }
- if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface);
- }
- } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) {
+ protected static boolean isValidEGLSurface(long eglDisplayHandle, long surfaceHandle) {
+ if( 0 == surfaceHandle ) {
+ return false;
+ }
+ 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();
if(DEBUG) {
- System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", eglDisplay: "+toHexString(eglDisplay)+", eglSurface: "+toHexString(eglSurface));
+ System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle));
}
- // Destroy the window surface
- if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) {
- throw new GLException("Error destroying window surface (eglDestroySurface)");
- }
- eglSurface = EGL.EGL_NO_SURFACE;
- if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
- }
- eglDisplay=EGL.EGL_NO_DISPLAY;
- eglConfig=null;
}
+ return eglSurfaceValid;
}
- protected final void swapBuffersImpl() {
- // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- if(!EGL.eglSwapBuffers(eglDisplay, eglSurface)) {
- throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
+ @Override
+ protected final void setRealizedImpl() {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": EGLDrawable.setRealized("+realized+"): NOP - "+surface);
}
}
- /**
- * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable.
- * Leave it here for later impl. of an EGLExternalDrawable.
- public int getWidth() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) {
- throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError()));
+ @Override
+ protected final void swapBuffersImpl(boolean doubleBuffered) {
+ if(doubleBuffered) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice();
+ // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
+ if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) {
+ throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this);
+ }
}
- return tmp[0];
}
- public int getHeight() {
- int[] tmp = new int[1];
- if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) {
- throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError()));
- }
- return tmp[0];
- } */
-
+ @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);
@@ -260,12 +177,13 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
}
+ @Override
public String toString() {
return getClass().getName()+"[realized "+isRealized()+
",\n\tfactory "+getFactory()+
",\n\tsurface "+getNativeSurface()+
- ",\n\teglSurface "+toHexString(eglSurface)+
- ",\n\teglConfig "+eglConfig+
+ ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+
+ ",\n\teglConfig "+surface.getGraphicsConfiguration()+
",\n\trequested "+getRequestedGLCapabilities()+
",\n\tchosen "+getChosenGLCapabilities()+"]";
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index 4b77bfa87..9ee0134f1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.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,93 +29,109 @@
* 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.nativewindow.*;
-import javax.media.opengl.*;
-import javax.media.opengl.GLProfile.ShutdownType;
-
-import com.jogamp.common.JogampRuntimeException;
-import com.jogamp.common.os.Platform;
-import com.jogamp.common.util.*;
-import com.jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
-
-import jogamp.opengl.*;
-
+import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.Collection;
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;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.MutableSurface;
+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;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+
+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.nio.Buffers;
+import com.jogamp.common.nio.PointerBuffer;
+import com.jogamp.common.os.Platform;
+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; // allow package access
+
+ /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK;
+
+ static {
+ Debug.initSingleton();
+ QUERY_EGL_ES_NATIVE_TK = Debug.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;
+ return dl.isFunctionAvailable("eglQuerySurfacePointerANGLE") ||
+ dl.isFunctionAvailable("glBlitFramebufferANGLE") ||
+ dl.isFunctionAvailable("glRenderbufferStorageMultisampleANGLE");
} else {
return false;
}
}
-
+
+ private static final boolean includesES1(GLDynamicLookupHelper dl) {
+ return dl.isFunctionAvailable("glLoadIdentity") &&
+ dl.isFunctionAvailable("glEnableClientState") &&
+ dl.isFunctionAvailable("glColorPointer");
+ }
+
public EGLDrawableFactory() {
super();
-
+
// Register our GraphicsConfigurationFactory implementations
// The act of constructing them causes them to be registered
EGLGraphicsConfigurationFactory.registerFactory();
// Check for other underlying stuff ..
- if(NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) {
+ 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 (Exception jre) { /* n/a .. */ }
}
- defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
-
- // FIXME: Probably need to move EGL from a static model
- // to a dynamic one, where there can be 2 instances
+ // 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 {
@@ -124,18 +140,18 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if(DEBUG) {
gle.printStackTrace();
}
- }
+ }
if(null!=tmp && tmp.isLibComplete()) {
eglES1DynamicLookupHelper = tmp;
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;
@@ -145,196 +161,545 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
if(DEBUG) {
gle.printStackTrace();
}
- }
+ }
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);
- }
- } else if (GLProfile.DEBUG) {
+ 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 (DEBUG || GLProfile.DEBUG) {
System.err.println("Info: EGLDrawableFactory: EGL ES2 - NOPE");
- }
+ }
+ }
+ if( null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper ) {
+ if(isANGLE && !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);
+ }
}
}
}
- protected final void destroy(ShutdownType shutdownType) {
+ @Override
+ protected final boolean isComplete() {
+ return null != sharedMap; // null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper;
+ }
+
+
+ @Override
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.shutdown");
+ }
if(null != sharedMap) {
+ if(DEBUG) {
+ dumpMap();
+ }
Collection<SharedResource> srl = sharedMap.values();
for(Iterator<SharedResource> sri = srl.iterator(); sri.hasNext(); ) {
SharedResource sr = sri.next();
if(DEBUG) {
- System.err.println("EGLDrawableFactory.destroy("+shutdownType+"): "+sr.device.toString());
- }
- final long eglDisplay = sr.device.getHandle();
- if(EGL.EGL_NO_DISPLAY != eglDisplay) {
- EGLDisplayUtil.eglTerminate(eglDisplay);
+ System.err.println("EGLDrawableFactory.shutdown: "+sr.device.toString());
}
+ sr.device.close();
}
sharedMap.clear();
+ sharedMapCreateAttempt.clear();
sharedMap = null;
+ sharedMapCreateAttempt = null;
+ }
+ if(null != defaultSharedResource) {
+ defaultSharedResource = null;
+ }
+ if(null != defaultDevice) {
+ defaultDevice.close();
+ defaultDevice = null;
}
- defaultDevice = null;
/**
* Pulling away the native library may cause havoc ..
*/
- if(ShutdownType.COMPLETE == shutdownType) {
- if(null != eglES1DynamicLookupHelper) {
- // eglES1DynamicLookupHelper.destroy();
- eglES1DynamicLookupHelper = null;
- }
- if(null != eglES2DynamicLookupHelper) {
- // eglES2DynamicLookupHelper.destroy();
- eglES2DynamicLookupHelper = null;
- }
+ if(null != eglES1DynamicLookupHelper) {
+ // eglES1DynamicLookupHelper.destroy();
+ eglES1DynamicLookupHelper = null;
+ }
+ if(null != eglES2DynamicLookupHelper) {
+ // eglES2DynamicLookupHelper.destroy();
+ eglES2DynamicLookupHelper = null;
}
EGLGraphicsConfigurationFactory.unregisterFactory();
+ EGLDisplayUtil.shutdown(DEBUG);
+ }
+
+ private void dumpMap() {
+ synchronized(sharedMap) {
+ System.err.println("EGLDrawableFactory.map "+sharedMap.size());
+ int i=0;
+ Set<String> keys = sharedMap.keySet();
+ for(Iterator<String> keyI = keys.iterator(); keyI.hasNext(); i++) {
+ String key = keyI.next();
+ 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 HashMap<String /*connection*/, SharedResource> sharedMap = new HashMap<String /*connection*/, SharedResource>();
- 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 hasPBufferES3ES2;
- SharedResource(EGLGraphicsDevice dev, boolean wasContextES1Created, boolean wasContextES2Created
- /*EGLDrawable draw, EGLContext ctxES1, EGLContext ctxES2 */) {
+ SharedResource(EGLGraphicsDevice dev,
+ boolean wasContextES1Created, boolean hasPBufferES1, GLRendererQuirks rendererQuirksES1, int ctpES1,
+ boolean wasContextES2Created, boolean wasContextES3Created,
+ boolean hasPBufferES3ES2, GLRendererQuirks rendererQuirksES3ES2, int ctpES3ES2) {
this.device = dev;
- // this.drawable = draw;
// this.contextES1 = ctxES1;
- // this.contextES2 = ctxES2;
this.wasES1ContextCreated = wasContextES1Created;
+ this.hasPBufferES1= hasPBufferES1;
+ 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;
}
- final EGLGraphicsDevice getDevice() { return device; }
- // final EGLDrawable getDrawable() { return drawable; }
+ @Override
+ public final boolean isValid() {
+ return wasES1ContextCreated || wasES2ContextCreated || wasES3ContextCreated;
+ }
+ @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 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
public final AbstractGraphicsDevice getDefaultDevice() {
return defaultDevice;
}
+ @Override
public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
// via mappings (X11/WGL/.. -> EGL) we shall be able to handle all types.
- return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
+ return null != sharedMap ; // null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper;
}
- /**
- private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) {
- boolean madeCurrent = false;
- final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile));
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
- final EGLContext context = (EGLContext) drawable.createContext(null);
- if (null != context) {
- context.setSynchronized(true);
- try {
- context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed");
- gle.printStackTrace();
- }
- } finally {
- context.destroy();
- }
+ private static List<GLCapabilitiesImmutable> getAvailableEGLConfigs(EGLGraphicsDevice eglDisplay, 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 = 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 */, false /* onlyFirstValid */);
}
- drawable.destroy();
}
- return madeCurrent;
- } */
-
- /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
- if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) {
- return null;
+ return new ArrayList<GLCapabilitiesImmutable>(0);
+ }
+
+ 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(AbstractGraphicsDevice adevice, int[] esProfile,
+ boolean[] hasPBuffer, GLRendererQuirks[] rendererQuirks, 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);
}
- String connection = adevice.getConnection();
- SharedResource sr;
- synchronized(sharedMap) {
- sr = (SharedResource) sharedMap.get(connection);
- }
- if(null==sr) {
- long eglDisplay = EGLDisplayUtil.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY);
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay));
+ if ( !GLProfile.isAvailable(adevice, profileString) ) {
+ if( DEBUG ) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: "+profileString+" n/a on "+adevice);
}
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError()));
+ 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+" ), "+
+ "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;
+ try {
+ final GLCapabilities reqCapsAny = new GLCapabilities(glp);
+ reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0);
+ reqCapsAny.setDoubleBuffered(false);
+
+ 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] ) {
+ // 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 {
+ // 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(defaultDevice, chosenCaps);
+ success = true;
+ }
+ if(DEBUG) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig() no pbuffer config available, detected !pbuffer config: "+success);
+ EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err);
+ }
+ }
+ eglDevice = defaultDevice; // reuse
+ } else {
+ // 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();
+ }
+ surface = upstreamSurface;
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface);
+ eglDevice.open();
+ if( DEBUG ) {
+ dumpEGLInfo("EGLDrawableFactory.mapAvailableEGLESConfig: ", eglDevice.getHandle());
+ }
+ hasPBuffer[0] = true;
}
- final EGLGraphicsDevice sharedDevice = new EGLGraphicsDevice(eglDisplay, connection, adevice.getUnitID());
- // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1);
- // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2);
- final boolean madeCurrentES1 = true; // FIXME
- final boolean madeCurrentES2 = true; // FIXME
- sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2);
- synchronized(sharedMap) {
- sharedMap.put(connection, sr);
+
+ if(null != surface) {
+ final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); // works w/ implicit pbuffer surface via proxy-hook
+ drawable.setRealized(true);
+ final EGLContext context = (EGLContext) drawable.createContext(null);
+ if (null != context) {
+ try {
+ context.makeCurrent(); // could cause exception
+ if(context.isCurrent()) {
+ final String glVersion = context.getGL().glGetString(GL.GL_VERSION);
+ if(null != glVersion) {
+ context.mapCurrentAvailableGLVersion(eglDevice);
+ if(eglDevice != adevice) {
+ context.mapCurrentAvailableGLVersion(adevice);
+ }
+ 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.mapAvailableEGLESConfig: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!");
+ }
+ }
+ }
+ } catch (Throwable t) {
+ if (DEBUG) {
+ System.err.println("EGLDrawableFactory.mapAvailableEGLESConfig: INFO: context create/makeCurrent failed");
+ t.printStackTrace();
+ }
+ } finally {
+ context.destroy();
+ }
+ }
+ drawable.setRealized(false);
+ }
+ } catch (Throwable t) {
+ if(DEBUG) {
+ System.err.println("Catched Exception on thread "+getThreadName());
+ t.printStackTrace();
+ }
+ success = false;
+ } finally {
+ if(null != downstreamSurface) {
+ downstreamSurface.destroyNotify();
+ }
+ if( defaultDevice != eglDevice ) { // don't close default device
+ if(null != eglDevice) {
+ eglDevice.close();
+ }
+ if(null != upstreamSurface) {
+ upstreamSurface.destroyNotify();
+ }
}
- if (DEBUG) {
- System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice);
- System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1);
- System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2);
- }
}
- return sr;
+ return success;
}
- protected final Thread getSharedResourceThread() {
- return null;
+ private final boolean needsToCreateSharedResource(String key, SharedResource[] existing) {
+ synchronized(sharedMap) {
+ final SharedResource sr = sharedMap.get(key);
+ if( null == sr ) {
+ final boolean createAttempted = sharedMapCreateAttempt.contains(key);
+ if(!createAttempted) {
+ sharedMapCreateAttempt.add(key);
+ }
+ return !createAttempted;
+ } else {
+ if(null != existing) {
+ existing[0] = sr;
+ }
+ return false;
+ }
+ }
}
-
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable();
+
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(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();
}
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception while EGL Shared Resource initialization");
- gle.printStackTrace();
+ if(null != defaultSharedResource) {
+ dumpMap();
+ throw new InternalError("defaultSharedResource already exist: "+defaultSharedResource);
}
+ 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");
+ }
+ final SharedResource[] existing = new SharedResource[] { null };
+ if ( !needsToCreateSharedResource(key, existing) ) {
+ return existing[0];
+ }
+ return createEGLSharedResourceImpl(adevice);
}
- return false;
}
-
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- return null; // n/a for EGL .. since we don't keep the resources
+
+ private SharedResource createEGLSharedResourceImpl(AbstractGraphicsDevice adevice) {
+ final boolean madeCurrentES1;
+ boolean[] hasPBufferES1 = new boolean[] { false };
+ boolean[] hasPBufferES3ES2 = new boolean[] { false };
+ // EGLContext[] eglCtxES1 = new EGLContext[] { null };
+ // EGLContext[] eglCtxES2 = new EGLContext[] { null };
+ GLRendererQuirks[] rendererQuirksES1 = new GLRendererQuirks[] { null };
+ GLRendererQuirks[] rendererQuirksES3ES2 = new GLRendererQuirks[] { null };
+ int[] ctpES1 = new int[] { -1 };
+ int[] ctpES3ES2 = new int[] { -1 };
+
+
+ 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]);
+ }
+ }
+ }
+ }
+ 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;
}
-
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
+
+ private void handleDontCloseX11DisplayQuirk(GLRendererQuirks quirks) {
+ if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) {
+ jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable();
}
+ }
+
+ @Override
+ protected final Thread getSharedResourceThread() {
return null;
}
- public boolean isANGLE() {
+ public final boolean isANGLE() {
return isANGLE;
}
-
+
+ @Override
public GLDynamicLookupHelper getGLDynamicLookupHelper(int esProfile) {
- if (2==esProfile) {
+ if ( 2==esProfile || 3==esProfile ) {
return eglES2DynamicLookupHelper;
} else if (1==esProfile) {
return eglES1DynamicLookupHelper;
@@ -343,20 +708,23 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
- if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) {
+ if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
return new ArrayList<GLCapabilitiesImmutable>(); // null
}
return EGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
}
+ @Override
protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new EGLOnscreenDrawable(this, target);
+ return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target));
}
+ @Override
protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -367,47 +735,104 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
throw new GLException("Non pbuffer not yet implemented");
}
// PBuffer GLDrawable Creation
- return new EGLPbufferDrawable(this, target);
+ return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target));
}
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ @Override
+ public boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
+ // SharedResource sr = getOrCreateEGLSharedResource(device);
+ // return sr.hasES1PBuffer() || sr.hasES2PBuffer();
return true;
}
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ @Override
+ protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ final boolean ownDevice;
+ final EGLGraphicsDevice device;
+ 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;
+ ownDevice = false;
+ }
+ 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);
+ }
+ return new WrappedSurface(config, 0, upstreamHook, ownDevice);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, 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 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) {
+ return null;
+ }
+ protected static long createPBufferSurfaceImpl(EGLGraphicsConfiguration config, int width, int height, boolean useTexture) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final int texFormat;
+
+ if(useTexture) {
+ texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
+ } else {
+ texFormat = EGL.EGL_NO_TEXTURE;
+ }
+
+ if (DEBUG) {
+ System.out.println("Pbuffer config: " + config);
+ }
+
+ 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) {
+ System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
+ }
+ return surf;
}
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- EGLGraphicsDevice device = (EGLGraphicsDevice) adevice;
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ @Override
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, 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);
}
-
+
+ @Override
protected GLContext createExternalGLContextImpl() {
AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_EGL);
return new EGLExternalContext(absScreen);
}
+ @Override
public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
return false;
}
+ @Override
protected GLDrawable createExternalGLDrawableImpl() {
throw new GLException("Not yet implemented");
}
-
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- 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
new file mode 100644
index 000000000..818f32607
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java
@@ -0,0 +1,60 @@
+package jogamp.opengl.egl;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+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.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public EGLDummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+ 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();
+ }
+ }
+
+ @Override
+ public final void destroy(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);
+ }
+ 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..ebe8f49c8 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,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.egl;
import com.jogamp.common.os.AndroidVersion;
+import com.jogamp.common.os.Platform;
import java.util.*;
@@ -38,10 +39,10 @@ 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,27 +52,23 @@ 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 == Platform.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>();
@@ -93,26 +90,26 @@ public abstract class EGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundle
return true;
}
}
-
- protected List<String> getEGLLibNamesList() {
+
+ protected final List<String> getEGLLibNamesList() {
List<String> eglLibNames = new ArrayList<String>();
-
- // this is the default EGL lib name, according to the spec
+
+ // 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 ff60a5262..aff18fc81 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.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,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.
- *
+ *
* Sun gratefully acknowledges that this software was originally authored
* and developed by Kenneth Bradley Russell and Christopher John Kline.
*/
@@ -36,51 +36,27 @@
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) {
super(null, null);
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES);
- getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
- }
-
- 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();
- }
-
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
- protected void makeCurrentImpl() throws GLException {
+ getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
+ @Override
protected void releaseImpl() throws GLException {
}
+ @Override
protected void destroyImpl() throws GLException {
}
-
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
- }
-
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
index f813edf86..e28b53235 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java
@@ -33,39 +33,43 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+
public class EGLGLCapabilities extends GLCapabilities {
private long eglcfg;
final private int eglcfgid;
- final private int renderableType;
+ final private int renderableType;
final private int nativeVisualID;
-
+
/**
- *
+ *
* @param eglcfg
* @param eglcfgid
* @param visualID native visualID if valid, otherwise VisualIDHolder.VID_UNDEFINED
- * @param glp desired GLProfile, or null if determined by renderableType
+ * @param glp desired GLProfile
* @param renderableType actual EGL renderableType
- *
+ *
* May throw GLException if given GLProfile is not compatible w/ renderableType
*/
public EGLGLCapabilities(long eglcfg, int eglcfgid, int visualID, GLProfile glp, int renderableType) {
- super( ( null != glp ) ? glp : getCompatible(renderableType) );
+ super( glp );
this.eglcfg = eglcfg;
this.eglcfgid = eglcfgid;
if(!isCompatible(glp, renderableType)) {
- throw new GLException("Incompatible "+glp+
- " with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]");
+ throw new GLException("Requested GLProfile "+glp+
+ " not compatible with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]");
}
this.renderableType = renderableType;
this.nativeVisualID = visualID;
}
+ @Override
public Object cloneMutable() {
return clone();
}
+ @Override
public Object clone() {
try {
return super.clone();
@@ -73,13 +77,13 @@ public class EGLGLCapabilities extends GLCapabilities {
throw new GLException(e);
}
}
-
+
final protected void setEGLConfig(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 {
switch(type) {
@@ -90,43 +94,50 @@ public class EGLGLCapabilities extends GLCapabilities {
return getNativeVisualID();
default:
throw new NativeWindowException("Invalid type <"+type+">");
- }
+ }
}
-
+
public static boolean isCompatible(GLProfile glp, 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(int renderableType) {
- if(0 != (renderableType & EGL.EGL_OPENGL_ES2_BIT) && GLProfile.isAvailable(GLProfile.GLES2)) {
- return GLProfile.get(GLProfile.GLES2);
+ public static GLProfile getCompatible(EGLGraphicsDevice device, 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);
}
- if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && GLProfile.isAvailable(GLProfile.GLES1)) {
- return GLProfile.get(GLProfile.GLES1);
+ if(0 != (renderableType & EGL.EGL_OPENGL_ES_BIT) && GLProfile.isAvailable(device, GLProfile.GLES1)) {
+ return GLProfile.get(device, GLProfile.GLES1);
}
if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) {
- return GLProfile.getDefault();
+ return GLProfile.getDefault(device);
}
return null;
}
-
+
public static StringBuilder renderableTypeToString(StringBuilder sink, int renderableType) {
if(null == sink) {
sink = new StringBuilder();
}
boolean first=true;
+ sink.append("0x").append(Integer.toHexString(renderableType)).append(": ");
if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) {
sink.append("GL"); first=false;
}
@@ -136,12 +147,16 @@ 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;
}
- return sink;
+ return sink;
}
-
+
+ @Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java
index 875bcb95b..88ed0be92 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.
*/
@@ -37,15 +37,16 @@
package jogamp.opengl.egl;
import java.nio.IntBuffer;
-import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
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,
+ EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen,
EGLGLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, 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(GLCapabilitiesImmutable capsRequested, AbstractGraphicsScreen absScreen, int eglConfigID) {
final AbstractGraphicsDevice absDevice = absScreen.getDevice();
if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) {
throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice");
@@ -81,9 +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 EGLGLCapabilities caps = EGLConfig2Capabilities(capsRequested.getGLProfile(), dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer(), false);
+ final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() );
+ final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsRequested);
+ final EGLGLCapabilities caps = EGLConfig2Capabilities(defaultQuirks, (EGLGraphicsDevice)absDevice, capsRequested.getGLProfile(), cfg, winattrmask, false);
return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser());
}
return null;
@@ -93,11 +108,12 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
public Object clone() {
return super.clone();
}
-
+
void updateGraphicsConfiguration() {
+ CapabilitiesImmutable capsChosen = getChosenCapabilities();
EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), capsChosen).chooseGraphicsConfiguration(
+ capsChosen, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
if(null!=newConfig) {
// FIXME: setScreen( ... );
setChosenCapabilities(newConfig.getChosenCapabilities());
@@ -108,260 +124,379 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple
}
public static long EGLConfigId2EGLConfig(long display, int configID) {
- int[] attrs = new int[] {
+ 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);
}
- static int EGLConfigDrawableTypeBits(final long display, final long config) {
+ public static boolean isEGLConfigValid(long display, 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(dbgCfgFailIntro+"EGL_CONFIG_ID"+dbgCfgFailForConfig+toHexString(config)+dbgCfgFailError+toHexString(eglErr));
+ }
+ return false;
+ }
+ return true;
+ }
+
+ static int EGLConfigDrawableTypeBits(final EGLGraphicsDevice device, final long config) {
int val = 0;
- int[] stype = new int[1];
- if(! EGL.eglGetConfigAttrib(display, 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 ) ) {
- val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
+ if ( 0 != ( _stype & EGL.EGL_PBUFFER_BIT ) ) {
+ val |= GLGraphicsConfigurationUtil.PBUFFER_BIT |
+ GLGraphicsConfigurationUtil.FBO_BIT;
}
-
return val;
}
- public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config,
- boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) {
- ArrayList bucket = new ArrayList();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- if( EGLConfig2Capabilities(bucket, glp, display, config, winattrmask, forceTransparentFlag) ) {
- return (EGLGLCapabilities) bucket.get(0);
- } else if ( relaxed && EGLConfig2Capabilities(bucket, glp, display, config, GLGraphicsConfigurationUtil.ALL_BITS, forceTransparentFlag) ) {
- return (EGLGLCapabilities) bucket.get(0);
- }
- return null;
- }
-
- public static boolean EGLConfig2Capabilities(ArrayList capsBucket,
- GLProfile glp, long display, long config,
- int winattrmask, boolean forceTransparentFlag) {
- final int allDrawableTypeBits = EGLConfigDrawableTypeBits(display, config);
- final int drawableTypeBits = winattrmask & allDrawableTypeBits;
-
- if( 0 == drawableTypeBits ) {
- return false;
- }
-
- final IntBuffer val = Buffers.newDirectIntBuffer(1);
+ /**
+ * @param defaultQuirks GLRendererQuirks of the EGLDrawableFactory's defaultDevice
+ * @param device
+ * @param glp desired GLProfile, may be null
+ * @param config
+ * @param winattrmask
+ * @param forceTransparentFlag
+ * @return
+ */
+ public static EGLGLCapabilities EGLConfig2Capabilities(GLRendererQuirks defaultQuirks, EGLGraphicsDevice device, GLProfile glp,
+ long config, int winattrmask, boolean forceTransparentFlag) {
+ final long display = device.getHandle();
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 false;
+ 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 false;
+ return null;
}
- rType = val.get(0);
-
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_NATIVE_VISUAL_ID, val)) {
- visualID = 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.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);
+ }
+ if(!EGLGLCapabilities.isCompatible(glp, rType)) {
+ if(DEBUG) {
+ System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+
+ " 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) {
if(DEBUG) {
System.err.println("config "+toHexString(config)+": "+gle);
}
- return false;
- }
-
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val)) {
- caps.setRedBits(val.get(0));
+ return null;
}
- if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val)) {
- caps.setGreenBits(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(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val)) {
- caps.setBlueBits(val.get(0));
+ // 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.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val)) {
- caps.setAlphaBits(val.get(0));
+ 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.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val)) {
- caps.setStencilBits(val.get(0));
+ 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.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val)) {
- caps.setDepthBits(val.get(0));
+ 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.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val)) {
- caps.setSampleBuffers(val.get(0)>0?true:false);
- caps.setNumSamples(val.get(0));
+ 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(!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_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) {
+ 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()));
} */
}
- return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, caps, drawableTypeBits );
+ 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(!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,
+ // we use EGL_RENDERABLE_TYPE derived profile as created in the EGLGLCapabilities constructor.
+ final int availableTypeBits = EGLConfigDrawableTypeBits(device, config);
+ final int drawableTypeBits = winattrmask & availableTypeBits;
+
+ if( 0 == drawableTypeBits ) {
+ return null;
+ }
+
+ return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps);
}
- public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) {
- int[] attrs = new int[32];
+ public static IntBuffer GLCapabilities2AttribList(GLCapabilitiesImmutable caps) {
+ final IntBuffer attrs = Buffers.newDirectIntBuffer(32);
int idx=0;
- attrs[idx++] = EGL.EGL_SURFACE_TYPE;
- attrs[idx++] = caps.isOnscreen() ? ( EGL.EGL_WINDOW_BIT ) : ( caps.isPBuffer() ? EGL.EGL_PBUFFER_BIT : EGL.EGL_PIXMAP_BIT ) ;
+ attrs.put(idx++, EGL.EGL_SURFACE_TYPE);
+ final int surfaceType;
+ if( caps.isOnscreen() ) {
+ surfaceType = EGL.EGL_WINDOW_BIT;
+ } else if( caps.isFBO() ) {
+ surfaceType = EGL.EGL_PBUFFER_BIT; // native replacement!
+ } else if( caps.isPBuffer() ) {
+ surfaceType = EGL.EGL_PBUFFER_BIT;
+ } else if( caps.isBitmap() ) {
+ surfaceType = EGL.EGL_PIXMAP_BIT;
+ } else {
+ throw new GLException("no surface type set in caps: "+caps);
+ }
+ 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(int width, int height, int texFormat) {
+ 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;
}
@@ -376,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 904110eb2..5cfa378cb 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
@@ -38,15 +38,14 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
-import javax.media.nativewindow.DefaultGraphicsScreen;
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;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLDrawableFactory;
@@ -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;
@@ -74,43 +74,51 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
static VisualIDHolder.VIDComparator EglCfgIDComparator = new VisualIDHolder.VIDComparator(VisualIDHolder.VIDType.EGL_CONFIG);
static GraphicsConfigurationFactory nativeGraphicsConfigurationFactory = null;
static GraphicsConfigurationFactory kdeglGraphicsConfigurationFactory = null;
-
+ static GraphicsConfigurationFactory fallbackGraphicsConfigurationFactory = null;
+
static void registerFactory() {
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) {
- nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, eglFactory);
+ nativeGraphicsConfigurationFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, eglFactory);
+ if(null != nativeGraphicsConfigurationFactory) {
+ fallbackGraphicsConfigurationFactory = nativeGraphicsConfigurationFactory;
+ } else {
+ 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, 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, 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;
-
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.egl.EGLGraphicsDevice.class, kdeglGraphicsConfigurationFactory);
+ 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) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (absScreen == null) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects");
}
@@ -132,21 +140,21 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
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, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
} else {
- // handle non native cases (X11, ..)
- if(null == nativeGraphicsConfigurationFactory) {
- throw new InternalError("Native GraphicsConfigurationFactory is null, but call issued for device: "+absDevice+" of type "+absDevice.getClass().getSimpleName());
+ // 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());
@@ -154,7 +162,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
cfg = chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable) capsChosen,
(GLCapabilitiesImmutable) capsRequested,
(GLCapabilitiesChooser) chooser,
- absScreen, VisualIDHolder.VID_UNDEFINED, false);
+ absScreen, nativeVisualID, false);
if(null == cfg || VisualIDHolder.VID_UNDEFINED == cfg.getVisualID(VIDType.NATIVE)) {
cfg = null;
if(DEBUG) {
@@ -165,23 +173,25 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(null == cfg) {
// fwd to native config factory (only X11 for now)
if(DEBUG) {
- System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+nativeGraphicsConfigurationFactory.getClass().getSimpleName());
+ System.err.println("EGLGraphicsConfigurationFactory.choose..: Delegate to "+fallbackGraphicsConfigurationFactory.getClass().getSimpleName());
}
- cfg = nativeGraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
- }
+ 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);
+ 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();
-
- List/*<EGLGLCapabilities>*/ availableCaps = null;
+ 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);
if(!EGL.eglGetConfigs(eglDisplay, null, 0, numConfigs)) {
@@ -197,19 +207,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("Graphics configuration get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(null, eglDisplay, 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,
+ AbstractGraphicsScreen absScreen, int nativeVisualID,
boolean forceTransparentFlag) {
if (capsChosen == null) {
capsChosen = new GLCapabilities(null);
@@ -222,101 +231,107 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
if(null==absDevice) {
throw new GLException("Null AbstractGraphicsDevice");
}
-
- final long eglDisplay;
+
+ final EGLGraphicsDevice eglDevice;
final boolean ownEGLDisplay;
- if( !(absDevice instanceof EGLGraphicsDevice) ) {
- eglDisplay = EGLDisplayUtil.eglGetDisplay(absDevice.getHandle());
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Could not get EGL display from: "+absDevice);
- }
- if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) {
- throw new GLException("eglInitialize failed eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+absDevice+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- }
- ownEGLDisplay = true;
- } else {
- eglDisplay = absDevice.getHandle();
- if (eglDisplay == EGL.EGL_NO_DISPLAY) {
- throw new GLException("Invalid EGL display: "+absDevice);
+ if( absDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) absDevice;
+ if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) {
+ throw new GLException("Invalid EGL display: "+eglDevice);
}
ownEGLDisplay = false;
+ } else {
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(absDevice.getHandle(), absDevice.getConnection(), absDevice.getUnitID());
+ eglDevice.open();
+ ownEGLDisplay = true;
}
- EGLDrawableFactory factory = (EGLDrawableFactory) GLDrawableFactory.getEGLFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(absDevice) );
-
- GLProfile glp = capsChosen.getGLProfile();
- GLCapabilities fixedCaps;
-
- EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag);
+ final GLProfile glp = capsChosen.getGLProfile();
+ 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
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(8);
fixedCaps.setGreenBits(8);
fixedCaps.setBlueBits(8);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (1): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s0
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (2): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
//
// rgb565 - d16, s4
- fixedCaps = new GLCapabilities(glp);
+ final GLCapabilities fixedCaps = new GLCapabilities(glp);
+ fixedCaps.setSampleBuffers(true);
+ fixedCaps.setNumSamples(4);
fixedCaps.setRedBits(5);
fixedCaps.setGreenBits(6);
fixedCaps.setBlueBits(5);
fixedCaps.setDepthBits(16);
- fixedCaps.setSampleBuffers(true);
- fixedCaps.setNumSamples(4);
+ if( !capsChosen.isOnscreen() ) {
+ fixedCaps.setOnscreen(false);
+ fixedCaps.setPBuffer(capsChosen.isPBuffer());
+ fixedCaps.setFBO(capsChosen.isFBO());
+ }
if(DEBUG) {
System.err.println("trying fixed caps (3): "+fixedCaps);
}
- res = eglChooseConfig(eglDisplay, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
+ res = eglChooseConfig(eglDevice, fixedCaps, capsReq, chooser, absScreen, nativeVisualID, false);
}
if(null==res) {
throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]");
}
if(ownEGLDisplay) {
- ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
- EGLDisplayUtil.eglTerminate(eglDisplay);
+ ((EGLGLCapabilities) res.getChosenCapabilities()).setEGLConfig(0); // eglDisplay: EOL
+ eglDevice.close();
}
return res;
}
- static EGLGraphicsConfiguration eglChooseConfig(long eglDisplay,
+
+ static EGLGraphicsConfiguration eglChooseConfig(EGLGraphicsDevice device,
GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
AbstractGraphicsScreen absScreen,
int nativeVisualID, boolean forceTransparentFlag) {
+ final long eglDisplay = device.getHandle();
final GLProfile glp = capsChosen.getGLProfile();
- final boolean onscreen = capsChosen.isOnscreen();
- final boolean usePBuffer = capsChosen.isPBuffer();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- List/*<EGLGLCapabilities>*/ availableCaps = null;
+ final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+ List<GLCapabilitiesImmutable> availableCaps = null;
int recommendedIndex = -1;
long recommendedEGLConfig = -1;
IntBuffer numConfigs = Buffers.newDirectIntBuffer(1);
@@ -327,35 +342,58 @@ 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 maxConfigs: "+numConfigs.get(0));
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: eglDisplay "+toHexString(eglDisplay)+", "+capsChosen+", nativeVisualID "+toHexString(nativeVisualID));
+ 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()+
+ ", numEGLConfigs "+numEGLConfigs);
}
- final IntBuffer attrs = Buffers.newDirectIntBuffer(EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen));
+ final IntBuffer attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen);
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(glp, eglDisplay, 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);
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
@@ -368,7 +406,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
throw new GLException("EGLGraphicsConfiguration.eglChooseConfig: #2 Get all configs (eglGetConfigs) call failed, error "+toHexString(EGL.eglGetError()));
}
if (numConfigs.get(0) > 0) {
- availableCaps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs.get(0), winattrmask, forceTransparentFlag);
+ availableCaps = eglConfigs2GLCaps(device, glp, configs, numConfigs.get(0), winattrmask, forceTransparentFlag, false /* onlyFirsValid */);
}
}
@@ -376,10 +414,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, 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++) {
@@ -387,11 +427,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
}
- if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) {
- List/*<EGLGLCapabilities>*/ removedCaps = new ArrayList();
+ if( VisualIDHolder.VID_UNDEFINED != nativeVisualID ) { // implies !hasEGLChosenCaps
+ 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++;
@@ -404,10 +449,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");
@@ -415,46 +468,32 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
return null;
}
final EGLGLCapabilities chosenCaps = (EGLGLCapabilities) availableCaps.get(chosenIndex);
+ final EGLGraphicsConfiguration res = new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser);
if (DEBUG) {
- System.err.println("EGLGraphicsConfiguration.eglChooseConfig: X chosen :"+chosenIndex+", eglConfig: "+toHexString(chosenCaps.getEGLConfig())+", "+chosenCaps);
+ System.err.println("EGLGraphicsConfiguration.eglChooseConfig: X chosen :"+chosenIndex+", eglConfig: "+toHexString(chosenCaps.getEGLConfig())+": "+res);
}
- return new EGLGraphicsConfiguration(absScreen, chosenCaps, capsRequested, chooser);
+ return res;
}
- static List/*<GLCapabilitiesImmutable>*/ eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag) {
- ArrayList caps = new ArrayList(num);
+ static List<GLCapabilitiesImmutable> eglConfigs2GLCaps(EGLGraphicsDevice device, GLProfile glp, PointerBuffer configs, int num, int winattrmask, boolean forceTransparentFlag, boolean onlyFirstValid) {
+ final GLRendererQuirks defaultQuirks = GLRendererQuirks.getStickyDeviceQuirks( GLDrawableFactory.getEGLFactory().getDefaultDevice() );
+ List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(num);
for(int i=0; i<num; i++) {
- EGLGraphicsConfiguration.EGLConfig2Capabilities(caps, glp, eglDisplay, 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 caps;
+ return bucket;
}
- static void printCaps(String prefix, List/*GLCapabilitiesImmutable*/ caps, PrintStream out) {
+ static void printCaps(String prefix, List<GLCapabilitiesImmutable> caps, PrintStream out) {
for(int i=0; i<caps.size(); i++) {
out.println(prefix+"["+i+"] "+caps.get(i));
}
}
-
- static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsReq, GLCapabilitiesChooser chooser) {
- if(capsChosen.isOnscreen()) {
- throw new GLException("Error: Onscreen set: "+capsChosen);
- }
-
- if(capsChosen.getDoubleBuffered()) {
- // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN
- GLCapabilities caps2 = (GLCapabilities) capsChosen.cloneMutable();
- caps2.setDoubleBuffered(false);
- capsChosen = caps2;
- }
-
- DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(capsChosen, capsReq, chooser, screen, VisualIDHolder.VID_UNDEFINED, false);
- if (null == eglConfig) {
- throw new GLException("Couldn't create EGLGraphicsConfiguration from "+screen);
- } else if(DEBUG) {
- System.err.println("Chosen eglConfig: "+eglConfig);
- }
- return eglConfig;
- }
}
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 dd0a3db3a..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
+++ /dev/null
@@ -1,59 +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.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.opengl.*;
-import com.jogamp.gluegen.runtime.ProcAddressTable;
-import java.nio.*;
-import java.util.*;
-
-public class EGLOnscreenContext extends EGLContext {
- public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
- }
-
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 42f067b29..065f80dcb 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.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.
*/
@@ -48,12 +48,14 @@ public class EGLOnscreenDrawable extends EGLDrawable {
super(factory, component);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new EGLOnscreenContext(this, shareWith);
+ return new EGLContext(this, shareWith);
}
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null);
+ @Override
+ protected long createSurface(EGLGraphicsConfiguration config, int width, int height, 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 2cad7daac..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
+++ /dev/null
@@ -1,62 +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.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.opengl.*;
-import com.jogamp.gluegen.runtime.ProcAddressTable;
-import java.nio.*;
-import java.util.*;
-
-public class EGLPbufferContext extends EGLContext {
- public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- public int getFloatingPointMode() {
- return 0; // FIXME ??
- }
-
- public void bindPbufferToTexture() {
- throw new GLException("Not yet implemented");
- }
-
- public void releasePbufferFromTexture() {
- throw new GLException("Not yet implemented");
- }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index 28a23d294..45e39f5d1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.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,64 +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.opengl.egl;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
public class EGLPbufferDrawable extends EGLDrawable {
- private int texFormat;
protected static final boolean useTexture = false; // No yet ..
protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeSurface target) {
super(factory, target);
}
- protected void destroyImpl() {
- setRealized(false);
- }
-
- protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) {
- final AbstractGraphicsConfiguration config = getNativeSurface().getGraphicsConfiguration();
- final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
-
- if(useTexture) {
- texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ;
- } else {
- texFormat = EGL.EGL_NO_TEXTURE;
- }
-
- if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
- }
-
- NativeSurface nw = getNativeSurface();
- int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat);
- long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0);
- if (EGL.EGL_NO_SURFACE==surf) {
- throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError()));
- } else if(DEBUG) {
- System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf));
- }
- ((SurfaceChangeable)nw).setSurfaceHandle(surf);
- return surf;
+ @Override
+ protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) {
+ return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new EGLPbufferContext(this, 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
new file mode 100644
index 000000000..5b911576e
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -0,0 +1,217 @@
+package jogamp.opengl.egl;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.DefaultGraphicsScreen;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
+import javax.media.opengl.GLCapabilitiesImmutable;
+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 (i.e. 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) {
+ upstreamSurface = upstream;
+ if(upstreamSurface instanceof ProxySurface) {
+ final UpstreamSurfaceHook ush = ((ProxySurface)upstreamSurface).getUpstreamSurfaceHook();
+ if(ush instanceof UpstreamSurfaceHook.MutableSize) {
+ // offscreen NativeSurface w/ MutableSize (default)
+ upstreamSurfaceHookMutableSize = (UpstreamSurfaceHook.MutableSize) ush;
+ } else {
+ upstreamSurfaceHookMutableSize = null;
+ }
+ } else {
+ upstreamSurfaceHookMutableSize = null;
+ }
+ }
+
+ public final NativeSurface getUpstreamSurface() { return upstreamSurface; }
+
+ static String getThreadName() { return Thread.currentThread().getName(); }
+
+ @Override
+ public final void setSize(int width, int height) {
+ if(null != upstreamSurfaceHookMutableSize) {
+ upstreamSurfaceHookMutableSize.setSize(width, height);
+ }
+ }
+
+ @Override
+ public final void create(ProxySurface surface) {
+ final String dbgPrefix;
+ if(DEBUG) {
+ 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
+ ((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);
+ }
+ try {
+ evalUpstreamSurface(dbgPrefix, surface);
+ } finally {
+ upstreamSurface.unlockSurface();
+ }
+ }
+
+ private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) {
+ //
+ // evaluate nature of upstreamSurface, may create EGL instances if required
+ //
+
+ boolean isEGLSurfaceValid = true; // assume yes
+
+ final EGLGraphicsDevice eglDevice;
+ final AbstractGraphicsConfiguration aConfig;
+ {
+ final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration();
+ final AbstractGraphicsDevice surfaceDevice = null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null;
+ if(DEBUG) {
+ 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);
+ }
+
+ 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 );
+ }
+ }
+
+ 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()) ) {
+ // 'refresh' the native EGLConfig handle
+ capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID()));
+ if( 0 == capsChosen.getEGLConfig() ) {
+ throw new GLException("Refreshing native EGLConfig handle failed with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+capsChosen+" of "+aConfig);
+ }
+ final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
+ eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null);
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Refreshing eglConfig: "+eglConfig);
+ }
+ isEGLSurfaceValid = false;
+ } else {
+ eglConfig = (EGLGraphicsConfiguration) aConfig;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Reusing eglConfig: "+eglConfig);
+ }
+ }
+ } else {
+ final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex());
+ eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
+ capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false /* forceTransparencyFlag */);
+
+ if (null == eglConfig) {
+ throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen);
+ } else if(DEBUG) {
+ System.err.println(dbgPrefix+"Chosen eglConfig: "+eglConfig);
+ }
+ isEGLSurfaceValid = false;
+ }
+ surface.setGraphicsConfiguration(eglConfig);
+
+ if(isEGLSurfaceValid) {
+ isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle());
+ }
+ if(isEGLSurfaceValid) {
+ surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle());
+ surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Fin: Already valid EGL surface - use as-is: "+upstreamSurface);
+ }
+ } else {
+ surface.setSurfaceHandle(EGL.EGL_NO_SURFACE);
+ surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); // create/destroy in EGLDrawable
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Fin: EGL surface n/a - TBD: "+upstreamSurface);
+ }
+ }
+ }
+
+ @Override
+ public final void destroy(ProxySurface surface) {
+ if(EGLDrawableFactory.DEBUG) {
+ System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this);
+ }
+ 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();
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return upstreamSurface.getHeight();
+ }
+
+ @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+ "]";
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
new file mode 100644
index 000000000..e6d43d957
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java
@@ -0,0 +1,34 @@
+package jogamp.opengl.egl;
+
+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) {
+ if(surface instanceof EGLWrappedSurface) {
+ return (EGLWrappedSurface)surface;
+ }
+ return new EGLWrappedSurface(surface);
+ }
+
+ public EGLWrappedSurface(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);
+ }
+ }
+
+ @Override
+ 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..a4aa1c7c5 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,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.
@@ -125,7 +125,7 @@ import com.jogamp.common.nio.Buffers;
* <p/>
* <p/>
* Created 11-jan-2004
- *
+ *
* @author Erik Duijs
* @author Kenneth Russell
*/
@@ -155,7 +155,7 @@ public class ProjectDouble {
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;
@@ -227,7 +227,7 @@ public class ProjectDouble {
/**
* Method __gluMultMatrixVecd
- *
+ *
* @param matrix
* @param in
* @param out
@@ -244,7 +244,7 @@ public class ProjectDouble {
/**
* Method __gluMultMatrixVecd
- *
+ *
* @param matrix
* @param in
* @param out
@@ -265,7 +265,7 @@ public class ProjectDouble {
/**
* @param src
* @param inverse
- *
+ *
* @return
*/
private boolean __gluInvertMatrixd(double[] src, double[] inverse) {
@@ -335,7 +335,7 @@ public class ProjectDouble {
/**
* @param src
* @param inverse
- *
+ *
* @return
*/
private boolean __gluInvertMatrixd(DoubleBuffer src, DoubleBuffer inverse) {
@@ -525,7 +525,7 @@ public class ProjectDouble {
/**
* Method gluOrtho2D.
- *
+ *
* @param left
* @param right
* @param bottom
@@ -537,7 +537,7 @@ public class ProjectDouble {
/**
* Method gluPerspective.
- *
+ *
* @param fovy
* @param aspect
* @param zNear
@@ -570,7 +570,7 @@ public class ProjectDouble {
/**
* Method gluLookAt
- *
+ *
* @param eyex
* @param eyey
* @param eyez
@@ -631,7 +631,7 @@ public class ProjectDouble {
/**
* Method gluProject
- *
+ *
* @param objx
* @param objy
* @param objz
@@ -639,7 +639,7 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
public boolean gluProject(double objx,
@@ -685,7 +685,7 @@ public class ProjectDouble {
/**
* Method gluProject
- *
+ *
* @param objx
* @param objy
* @param objz
@@ -693,7 +693,7 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param win_pos
- *
+ *
* @return
*/
public boolean gluProject(double objx,
@@ -738,7 +738,7 @@ public class ProjectDouble {
/**
* Method gluUnproject
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -746,7 +746,7 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject(double winx,
@@ -799,7 +799,7 @@ public class ProjectDouble {
/**
* Method gluUnproject
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -807,7 +807,7 @@ public class ProjectDouble {
* @param projMatrix
* @param viewport
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject(double winx,
@@ -858,7 +858,7 @@ public class ProjectDouble {
/**
* Method gluUnproject4
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -869,7 +869,7 @@ public class ProjectDouble {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject4(double winx,
@@ -923,7 +923,7 @@ public class ProjectDouble {
/**
* Method gluUnproject4
- *
+ *
* @param winx
* @param winy
* @param winz
@@ -934,7 +934,7 @@ public class ProjectDouble {
* @param near
* @param far
* @param obj_pos
- *
+ *
* @return
*/
public boolean gluUnProject4(double winx,
@@ -987,7 +987,7 @@ public class ProjectDouble {
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
@@ -1014,7 +1014,7 @@ public class ProjectDouble {
/**
* Method gluPickMatrix
- *
+ *
* @param x
* @param y
* @param deltaX
diff --git a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java
index 3f8a76535..717b1255c 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,15 +115,17 @@
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.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
@@ -139,25 +141,30 @@ 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(GL gl, boolean useGLSL, ShaderState st, 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();
}
+ @Override
public void enableImmModeSink(boolean val) {
if(gl.isGL2()) {
immModeSinkEnabled=val;
@@ -169,10 +176,12 @@ public class GLUquadricImpl implements GLUquadric {
}
}
+ @Override
public boolean isImmModeSinkEnabled() {
return immModeSinkEnabled;
}
+ @Override
public void setImmMode(boolean val) {
if(immModeSinkEnabled) {
immModeSinkImmediate=val;
@@ -181,30 +190,44 @@ public class GLUquadricImpl implements GLUquadric {
}
}
+ @Override
public boolean getImmMode() {
return immModeSinkImmediate;
}
+ @Override
public ImmModeSink replaceImmModeSink() {
if(!immModeSinkEnabled) return null;
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;
}
+ @Override
public void resetImmModeSink(GL gl) {
if(immModeSinkEnabled) {
immModeSink.reset(gl);
@@ -212,7 +235,7 @@ public class GLUquadricImpl implements GLUquadric {
}
/**
- * specifies the draw style for quadrics.
+ * specifies the draw style for quadrics.
*
* The legal values are as follows:
*
@@ -226,7 +249,7 @@ 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) {
@@ -243,7 +266,7 @@ 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) {
@@ -260,7 +283,7 @@ 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) {
@@ -275,7 +298,7 @@ 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) {
@@ -430,7 +453,7 @@ public class GLUquadricImpl implements GLUquadric {
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);
@@ -495,10 +518,10 @@ public class GLUquadricImpl implements GLUquadric {
glNormal3f(gl, 0.0f, 0.0f, -1.0f);
}
}
-
+
da = 2.0f * PI / slices;
dr = (outerRadius - innerRadius) / loops;
-
+
switch (drawStyle) {
case GLU.GLU_FILL:
{
@@ -514,7 +537,7 @@ public class GLUquadricImpl implements GLUquadric {
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 +555,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)
@@ -631,18 +654,18 @@ 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),
@@ -655,11 +678,10 @@ public class GLUquadricImpl implements GLUquadric {
int loops,
float startAngle,
float sweepAngle) {
- int i, j, max;
+ int i, j;
float[] sinCache = new float[CACHE_SIZE];
float[] cosCache = new float[CACHE_SIZE];
float angle;
- float x, y;
float sintemp, costemp;
float deltaRadius;
float radiusLow, radiusHigh;
@@ -770,7 +792,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) {
@@ -984,7 +1006,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;
@@ -1188,7 +1210,7 @@ public class GLUquadricImpl implements GLUquadric {
*/
private void normal3f(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;
diff --git a/src/jogl/classes/jogamp/opengl/glu/Glue.java b/src/jogl/classes/jogamp/opengl/glu/Glue.java
index 636d17f29..2ad3d8c89 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 ) {
return( __gluNurbsErrors[ errno ] );
}
-
+
private static String[] __gluTessErrors = {
" ",
"gluTessBeginPolygon() must precede a gluTessEndPolygon",
@@ -107,7 +107,7 @@ public class Glue {
"a coordinate is too large",
"need combine callback"
};
-
+
public static String __gluTessErrorString( 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..ffb8d9471 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,11 +71,11 @@ public class Error {
"",
"invalid operation"
};
-
+
/** Creates a new instance of Error */
public Error() {
}
-
+
public static String gluErrorString( 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..4213dfd46 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2CurveEvaluator.java
@@ -48,7 +48,7 @@ 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;
@@ -92,6 +92,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
/**
* Pushes eval bit
*/
+ @Override
public void bgnmap1f() {
// DONE
if (output_triangles) {
@@ -108,6 +109,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
/**
* Pops all OpenGL attributes
*/
+ @Override
public void endmap1f() {
// DONE
if (output_triangles) {
@@ -127,6 +129,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param order curve order
* @param ps control points
*/
+ @Override
public void map1f(int type, float ulo, float uhi, int stride, int order,
CArrayOfFloats ps) {
if (output_triangles) {
@@ -153,6 +156,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
* Calls opengl enable
* @param type what to enable
*/
+ @Override
public void enable(int type) {
// DONE
gl.glEnable(type);
@@ -164,6 +168,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param u1 low u
* @param u2 high u
*/
+ @Override
public void mapgrid1f(int nu, float u1, float u2) {
if (output_triangles) {
// System.out.println("TODO curveevaluator.mapgrid1f");
@@ -179,6 +184,7 @@ class GL2CurveEvaluator implements CurveEvaluator {
* @param from lowest param
* @param to highest param
*/
+ @Override
public void mapmesh1f(int style, int from, int to) {
/* //DEBUG drawing control points
this.poradi++;
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..e9c9fca3f 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GL2SurfaceEvaluator.java
@@ -72,6 +72,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
/**
* Pushes eval bit
*/
+ @Override
public void bgnmap2f() {
if (output_triangles) {
@@ -88,6 +89,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* Sets glPolygonMode
* @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT)
*/
+ @Override
public void polymode(int style) {
if (!output_triangles) {
switch (style) {
@@ -109,6 +111,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
/**
* Pops all attributes
*/
+ @Override
public void endmap2f() {
// TODO Auto-generated method stub
if (output_triangles) {
@@ -126,6 +129,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vlo
* @param vhi
*/
+ @Override
public void domain2f(float ulo, float uhi, float vlo, float vhi) {
// DONE
}
@@ -139,6 +143,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param v0 lowest v
* @param v1 highest v
*/
+ @Override
public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) {
if (output_triangles) {
@@ -157,6 +162,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vmin minimum V
* @param vmax maximum V
*/
+ @Override
public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) {
if (output_triangles) {
// System.out.println("TODO openglsurfaceavaluator.mapmesh2f output_triangles");
@@ -195,6 +201,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* @param vorder surface order in v direction
* @param pts control points
*/
+ @Override
public void map2f(int type, float ulo, float uhi, int ustride, int uorder,
float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) {
// TODO Auto-generated method stub
@@ -210,6 +217,7 @@ class GL2SurfaceEvaluator implements SurfaceEvaluator {
* Calls opengl enable
* @param type what to enable
*/
+ @Override
public void enable(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..f83b3a805 100644
--- a/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java
+++ b/src/jogl/classes/jogamp/opengl/glu/gl2/nurbs/GLUgl2nurbsImpl.java
@@ -43,9 +43,9 @@ import javax.media.opengl.glu.GLUnurbs;
/**
* Base object for working with NURBS curves and surfaces
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class GLUgl2nurbsImpl implements GLUnurbs {
@@ -272,7 +272,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Sets domain distance for dom.dist. sampling in u direction
- *
+ *
* @param d
* distance
*/
@@ -283,7 +283,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Sets domain distance for dom.dist. sampling in v direction
- *
+ *
* @param d
* distance
*/
@@ -303,7 +303,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Calls a method with given name and passes argumet
- *
+ *
* @param name
* name of a method to be called
* @param arg
@@ -329,7 +329,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Calls a method with given name
- *
+ *
* @param name
* name of a method to be called
*/
@@ -349,7 +349,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Begins a NURBS curve
- *
+ *
* @param o_curve
* curve object
*/
@@ -381,7 +381,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Begins new surface
- *
+ *
* @param o_surface
* surface object
*/
@@ -503,7 +503,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Method for handling error codes
- *
+ *
* @param i
* error code
*/
@@ -539,7 +539,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Make a NURBS curve
- *
+ *
* @param nknots
* number of knots in knot vector
* @param knot
@@ -587,7 +587,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Check knot vector specification
- *
+ *
* @param knots
* knot vector
* @param msg
@@ -607,7 +607,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Draw a curve
- *
+ *
* @param o_nurbscurve
* NURBS curve object
*/
@@ -660,7 +660,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Draw NURBS surface
- *
+ *
* @param o_nurbssurface
* NURBS surface object
*/
@@ -704,7 +704,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Define a map of given properties
- *
+ *
* @param type
* map type
* @param rational
@@ -719,7 +719,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Set NURBS property
- *
+ *
* @param type
* property type
* @param tag
@@ -744,7 +744,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Set parameters of existing property
- *
+ *
* @param prop
* property
*/
@@ -755,7 +755,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Set given property to rendering hints
- *
+ *
* @param prop
* property to be set
*/
@@ -767,7 +767,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Sets wheteher we use domain distance sampling
- *
+ *
* @param i
* domain distance sampling flag
*/
@@ -805,7 +805,7 @@ public class GLUgl2nurbsImpl implements GLUnurbs {
/**
* Make NURBS surface
- *
+ *
* @param sknot_count
* number of knots in s direction
* @param sknot
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/BuildMipmap.java
index f5fe17a7b..81a99beab 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
@@ -64,7 +64,7 @@ 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 ) {
@@ -78,34 +78,34 @@ public class BuildMipmap {
int maxsize;
int cmpts;
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,
+ newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, 1, format,
GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
} catch( 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 );
-
+
// if swap_bytes was set, swapping occurred in fill_image
gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
-
+
for( level = userLevel; level <= levels; level++ ) {
if( newImage_width == newwidth ) {
// user newimage for this level
@@ -132,10 +132,10 @@ 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,
+ gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0,
format, GL2.GL_UNSIGNED_SHORT, newImage );
}
}
@@ -148,10 +148,10 @@ public class BuildMipmap {
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) );
-
+
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];
@@ -166,37 +166,37 @@ public class BuildMipmap {
int maxsize;
int cmpts;
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,
+ newImage = Buffers.newDirectByteBuffer( Mipmap.image_size( width, height,
format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
} catch( 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 );
-
+
// if swap_bytes is set, swapping occurred in fill_image
gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
-
+
for( level = 0; level < levels; level++ ) {
if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
newImage.rewind();
@@ -216,13 +216,13 @@ public class BuildMipmap {
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();
@@ -241,10 +241,10 @@ public class BuildMipmap {
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) );
-
+
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,
@@ -263,19 +263,19 @@ public class BuildMipmap {
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();
-
+
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 +283,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 +294,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 );
-
+
level = userLevel;
-
+
// already power of two square
if( width == newwidth && height == newheight ) {
// use usersImage for level userLevel
@@ -333,7 +333,7 @@ public class BuildMipmap {
}
int nextWidth = newwidth / 2;
int nextHeight = newheight / 2;
-
+
// clamp to 1
if( nextWidth < 1 ) {
nextWidth = 1;
@@ -342,7 +342,7 @@ public class BuildMipmap {
nextHeight = 1;
}
memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
-
+
try {
switch( type ) {
case( GL2.GL_UNSIGNED_BYTE ):
@@ -452,7 +452,7 @@ public class BuildMipmap {
if( newheight < 1 ) {
newheight = 1;
}
-
+
myswap_bytes = false;
rowsize = newwidth * group_size;
memReq = Mipmap.image_size( newwidth, newheight, format, type );
@@ -498,7 +498,7 @@ public class BuildMipmap {
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 ):
@@ -535,15 +535,15 @@ public class BuildMipmap {
data.position( mark );
switch( type ) {
case( GL2.GL_UNSIGNED_BYTE ):
- ScaleInternal.scale_internal_ubyte( cmpts, width, height, data,
+ 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,
+ 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,
+ ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth,
newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes );
break;
case( GL2.GL_SHORT ):
@@ -620,7 +620,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,7 +630,7 @@ public class BuildMipmap {
if( nextHeight < 1 ) {
nextHeight = 1;
}
-
+
memReq = Mipmap.image_size( nextWidth, nextHeight, format, type );
try {
switch( type ) {
@@ -670,7 +670,7 @@ public class BuildMipmap {
// level userLevel is in srcImage; nothing saved yet
level = userLevel;
}
-
+
gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
if( baseLevel <= level && level <= maxLevel ) {
srcImage.rewind();
@@ -685,7 +685,7 @@ public class BuildMipmap {
}
}
}
-
+
level++; // update current level for the loop
for( ; level <= levels; level++ ) {
srcImage.rewind();
@@ -754,12 +754,12 @@ public class BuildMipmap {
assert( false );
break;
}
-
+
// swap dstImage and srcImage
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( newwidth > 1 ) {
newwidth /= 2;
rowsize /= 2;
@@ -769,7 +769,7 @@ public class BuildMipmap {
}
// compute amount to pad per row if any
int rowPad = rowsize % psm.getUnpackAlignment();
-
+
// should row be padded
if( rowPad == 0 ) {
// call teximage with srcImage untouched since its not padded
@@ -792,7 +792,7 @@ public class BuildMipmap {
int ii, jj;
int dstTrav;
int srcTrav;
-
+
// allocate new image for mipmap of size newRowLength x newheight
ByteBuffer newMipmapImage = null;
try {
@@ -813,7 +813,7 @@ public class BuildMipmap {
newMipmapImage.put( srcImage.get() );
}
}
-
+
// and use this new image for mipmapping instead
if( baseLevel <= level && level <= maxLevel ) {
newMipmapImage.rewind();
@@ -833,10 +833,10 @@ public class BuildMipmap {
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) );
-
+
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];
@@ -850,22 +850,22 @@ public class BuildMipmap {
int memReq;
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;
@@ -878,7 +878,7 @@ public class BuildMipmap {
int iter;
int iter2;
int i, j;
-
+
try {
newImage = Buffers.newDirectByteBuffer( Mipmap.image_size(width, height, format, GL2.GL_UNSIGNED_BYTE ) );
} catch( OutOfMemoryError err ) {
@@ -896,7 +896,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,13 +906,13 @@ 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 );
-
+
for( level = 0; level <= levels; level++ ) {
if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) {
// use newImage for this level
@@ -937,7 +937,7 @@ public class BuildMipmap {
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
-
+
newImage_width = newwidth[0];
newImage_height = newheight[0];
newImage.rewind();
@@ -956,10 +956,10 @@ public class BuildMipmap {
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 ) ) ;
-
+
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,
@@ -977,19 +977,19 @@ public class BuildMipmap {
int maxSize;
int cmpts;
int mark=-1;
-
+
boolean myswapBytes;
int groupsPerLine, elementSize, groupSize;
int rowsPerImage, imageSize;
int rowSize, padding;
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 +1002,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 +1013,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 );
-
+
level = userLevel;
-
+
if( width == newWidth && height == newHeight && depth == newDepth ) {
// use usersImage for level userlevel
if( baseLevel <= level && level <= maxLevel ) {
@@ -1068,7 +1068,7 @@ public class BuildMipmap {
int nextWidth = newWidth / 2;
int nextHeight = newHeight / 2;
int nextDepth = newDepth / 2;
-
+
// clamp to one
if( nextWidth < 1 ) {
nextWidth = 1;
@@ -1116,13 +1116,13 @@ public class BuildMipmap {
gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() );
return( GLU.GLU_OUT_OF_MEMORY );
}
-
+
if( dstImage != null ) {
switch( type ) {
case( GL2.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,
@@ -1145,7 +1145,7 @@ public class BuildMipmap {
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;
@@ -1257,7 +1257,7 @@ public class BuildMipmap {
if( newDepth < 1 ) {
newDepth = 1;
}
-
+
myswapBytes = false;
rowSize = newWidth * groupSize;
imageSize = rowSize * newHeight;
@@ -1302,7 +1302,7 @@ public class BuildMipmap {
gl.glPixelStorei( GL2.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 {
@@ -1343,10 +1343,10 @@ public class BuildMipmap {
gl.glPixelStorei( GL2.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 +1354,7 @@ public class BuildMipmap {
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( levels != 0 ) {
int nextWidth = newWidth / 2;
int nextHeight = newHeight / 2;
@@ -1409,7 +1409,7 @@ public class BuildMipmap {
// level userLevel is in srcImage; nothing saved yet
level = userLevel;
}
-
+
gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE );
if( baseLevel <= level && level <= maxLevel ) {
usersImage.position( mark );
@@ -1541,11 +1541,11 @@ public class BuildMipmap {
assert( false );
break;
}
-
+
tempImage = srcImage;
srcImage = dstImage;
dstImage = tempImage;
-
+
if( newWidth > 1 ) {
newWidth /= 2;
rowSize /= 2;
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..0c155ff96 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..5208ea537 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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);
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..1bf8abcc3 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..c86b39e63 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,11 +51,12 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract233rev implements Extract {
-
+
/** Creates a new instance of Extract223rev */
public Extract233rev() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
// 11100000 == 0xe0
// 00011100 == 0x1c
@@ -65,16 +66,17 @@ public class Extract233rev implements Extract {
extractComponents[1] = (float)((ubyte & 0x38) >> 3) / 7.0f;
extractComponents[2] = (float)((ubyte & 0xC0) >> 6) / 3.0f;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..706f0c3f2 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,11 +51,12 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class Extract332 implements Extract {
-
+
/** Creates a new instance of Extract332 */
public Extract332() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) {
// 11100000 == 0xe0
// 00011100 == 0x1c
@@ -65,16 +66,17 @@ public class Extract332 implements Extract {
extractComponents[1] = (float)((ubyte & 0x1c) >> 2) / 7.0f;
extractComponents[2] = (float)((ubyte & 0x03)) / 3.0f;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..182d66ce2 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..52ecdc17c 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..21f53aa1d 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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 ) );
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..7408c45b2 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..adaafa7ea 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..be155d578 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..294e60e12 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() {
}
-
+
+ @Override
public void extract( boolean isSwap, ByteBuffer packedPixel, 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;
}
-
+
+ @Override
public void shove( float[] shoveComponents, int index, 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..1dd8bff8a 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,11 +51,12 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractFloat implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractFloat */
public ExtractFloat() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer data ) {
float f = 0;
if( isSwap ) {
@@ -66,7 +67,8 @@ public class ExtractFloat implements ExtractPrimitive {
assert( f <= 1.0f );
return( f );
}
-
+
+ @Override
public void shove( double value, int index, 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..dcbe52a40 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,17 +51,19 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class ExtractSByte implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUByte */
public ExtractSByte() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer sbyte ) {
byte b = sbyte.get();
assert( b <= 127 );
return( b );
}
-
+
+ @Override
public void shove( double value, int index, 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..547bd944a 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,11 +51,12 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractSInt implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractSInt */
public ExtractSInt() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer uint ) {
int i = 0;
if( isSwap ) {
@@ -66,7 +67,8 @@ public class ExtractSInt implements ExtractPrimitive {
assert( i <= 0x7FFFFFFF );
return( i );
}
-
+
+ @Override
public void shove( double value, int index, ByteBuffer data ) {
assert(0.0 <= value && value < Integer.MAX_VALUE);
IntBuffer ib = data.asIntBuffer();
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractSShort.java
index 979c3b449..7dc172976 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,11 +51,12 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractSShort implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractSShort */
public ExtractSShort() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer ushort ) {
short s = 0;
if( isSwap ) {
@@ -66,7 +67,8 @@ public class ExtractSShort implements ExtractPrimitive {
assert( s <= 32767 );
return( s );
}
-
+
+ @Override
public void shove( double value, int index, ByteBuffer data ) {
assert(0.0 <= value && value < 32768.0);
ShortBuffer sb = data.asShortBuffer();
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUByte.java
index 4d14212ab..3e933811c 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,17 +51,19 @@ import java.nio.ByteBuffer;
* @author Administrator
*/
public class ExtractUByte implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUByte */
public ExtractUByte() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer ubyte ) {
int i = 0x000000FF & ubyte.get();
assert( i <= 255 );
return( i );
}
-
+
+ @Override
public void shove( double value, int index, ByteBuffer data ) {
assert(0.0 <= value && value < 256.0);
data.position( index );
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUInt.java
index c088ca301..1c34828b3 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,11 +51,12 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractUInt implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtractUInt */
public ExtractUInt() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer uint ) {
long i = 0;
if( isSwap ) {
@@ -66,7 +67,8 @@ public class ExtractUInt implements ExtractPrimitive {
assert( i <= 0xFFFFFFFF );
return( i );
}
-
+
+ @Override
public void shove( double value, int index, ByteBuffer data ) {
assert(0.0 <= value && value < 0xFFFFFFFF);
IntBuffer ib = data.asIntBuffer();
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/ExtractUShort.java
index 81db60f0f..8e0d25c42 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,11 +51,12 @@ import java.nio.*;
* @author Administrator
*/
public class ExtractUShort implements ExtractPrimitive {
-
+
/** Creates a new instance of ExtracUShort */
public ExtractUShort() {
}
-
+
+ @Override
public double extract( boolean isSwap, ByteBuffer ushort ) {
int i = 0;
if( isSwap ) {
@@ -66,7 +67,8 @@ public class ExtractUShort implements ExtractPrimitive {
assert( i <= 65535 );
return( i );
}
-
+
+ @Override
public void shove( double value, int index, ByteBuffer data ) {
assert(0.0 <= value && value < 65536.0);
ShortBuffer sb = data.asShortBuffer();
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/HalveImage.java
index 7549044ba..184c5fda8 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,11 +52,11 @@ 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 ) {
int i, j, k;
@@ -64,11 +64,11 @@ public class HalveImage {
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,7 +91,7 @@ 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 ) {
@@ -99,19 +99,19 @@ public class HalveImage {
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,9 +133,9 @@ public class HalveImage {
t += ysize;
}
}
-
+
public static void halve1Dimage_ubyte( int components, int width, int height,
- ByteBuffer datain, ByteBuffer dataout,
+ ByteBuffer datain, ByteBuffer dataout,
int element_size, int ysize, int group_size ) {
int halfWidth = width / 2;
int halfHeight = height / 2;
@@ -143,14 +143,14 @@ public class HalveImage {
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;
@@ -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,7 +202,7 @@ 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 ) {
@@ -211,7 +211,7 @@ public class HalveImage {
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,7 +244,7 @@ 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 ) {
@@ -254,14 +254,14 @@ public class HalveImage {
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++ ) {
@@ -284,7 +284,7 @@ public class HalveImage {
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,7 +303,7 @@ 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 ) {
@@ -319,10 +319,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,7 +364,7 @@ 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 ) {
@@ -373,14 +373,14 @@ public class HalveImage {
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++ ) {
@@ -410,7 +410,7 @@ public class HalveImage {
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++ ) {
@@ -437,7 +437,7 @@ 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 ) {
@@ -453,10 +453,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++ ) {
@@ -504,7 +504,7 @@ 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 ) {
@@ -513,14 +513,14 @@ public class HalveImage {
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++ ) {
@@ -550,7 +550,7 @@ public class HalveImage {
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++ ) {
@@ -577,7 +577,7 @@ 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 ) {
@@ -586,7 +586,7 @@ public class HalveImage {
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 +594,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,7 +643,7 @@ 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 ) {
@@ -652,14 +652,14 @@ public class HalveImage {
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++ ) {
@@ -689,7 +689,7 @@ public class HalveImage {
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++ ) {
@@ -716,7 +716,7 @@ 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 ) {
@@ -725,7 +725,7 @@ public class HalveImage {
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 +733,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,7 +785,7 @@ 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 ) {
@@ -794,14 +794,14 @@ public class HalveImage {
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++ ) {
@@ -831,7 +831,7 @@ public class HalveImage {
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++ ) {
@@ -858,7 +858,7 @@ 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 ) {
@@ -874,10 +874,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,7 +920,7 @@ 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 ) {
@@ -929,14 +929,14 @@ public class HalveImage {
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++ ) {
@@ -966,7 +966,7 @@ public class HalveImage {
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++ ) {
@@ -993,9 +993,9 @@ 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,
+
+ public static void halveImagePackedPixel( int components, Extract extract, int width,
+ int height, ByteBuffer datain, ByteBuffer dataout,
int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) {
if( width == 1 || height == 1 ) {
assert( !( width == 1 && height == 1 ) );
@@ -1004,19 +1004,19 @@ public class HalveImage {
return;
}
int ii, jj;
-
+
int halfWidth = width / 2;
int halfHeight = height / 2;
int src = 0;
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];
int cc;
-
+
datain.position( src );
extract.extract( isSwap, datain, extractTotals[0] );
datain.position( src + pixelSizeInBytes );
@@ -1045,7 +1045,7 @@ 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 ) {
@@ -1053,23 +1053,23 @@ public class HalveImage {
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];
int cc;
-
+
datain.position( src );
extract.extract( isSwap, datain, extractTotals[0] );
datain.position( src + pixelSizeInBytes );
@@ -1090,17 +1090,17 @@ public class HalveImage {
}
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];
@@ -1128,7 +1128,7 @@ 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,
@@ -1140,26 +1140,26 @@ public class HalveImage {
int src = 0;
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];
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 +1167,7 @@ public class HalveImage {
}
totals[cc] /= BOX2;
} // for cc
-
+
extract.shove( totals, outIndex, dataOut );
outIndex++;
// skip over to next group of 2
@@ -1175,13 +1175,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];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + pixelSizeInBytes );
@@ -1190,10 +1190,10 @@ 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++ ) {
@@ -1209,13 +1209,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];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + rowSizeInBytes );
@@ -1224,10 +1224,10 @@ 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++ ) {
@@ -1243,7 +1243,7 @@ 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,
@@ -1255,25 +1255,25 @@ public class HalveImage {
int src = 0;
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];
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];
@@ -1282,7 +1282,7 @@ public class HalveImage {
totals[cc] += extractTotals[kk][cc];
}
totals[cc] /= (double)BOX2;
-
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1290,12 +1290,12 @@ 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;
@@ -1303,7 +1303,7 @@ public class HalveImage {
int kk;
double totals[] = new double[4];
double extractTotals[][] = new double[BOX4][4];
-
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + groupSizeInBytes );
@@ -1312,7 +1312,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] +
@@ -1322,7 +1322,7 @@ public class HalveImage {
totals[cc] += extractTotals[kk][cc];
}
totals[cc] /= (double)BOX4;
-
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1337,7 +1337,7 @@ 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;
@@ -1345,7 +1345,7 @@ public class HalveImage {
int kk;
double totals[] = new double[4];
double extractTotals[][] = new double[BOX4][4];
-
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + rowSizeInBytes );
@@ -1354,8 +1354,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] +
@@ -1365,7 +1365,7 @@ public class HalveImage {
totals[cc] += extractTotals[kk][cc];
}
totals[cc] /= (double)BOX4;
-
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
src += elementSizeInBytes;
@@ -1380,32 +1380,32 @@ 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 ) {
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;
int src = 0;
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++ ) {
@@ -1414,7 +1414,7 @@ public class HalveImage {
int kk;
double totals[] = new double[4];
double extractTotals[][] = new double[BOX8][4];
-
+
dataIn.position( src );
extractTotals[0][cc] = extract.extract( isSwap, dataIn );
dataIn.position( src + groupSizeInBytes );
@@ -1431,17 +1431,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;
-
+
extract.shove( totals[cc], outIndex, dataOut );
outIndex++;
-
+
src += elementSizeInBytes;
} // for cc
// skip over to next square of 4
@@ -1456,40 +1456,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,
+ int width, int height, int depth, ByteBuffer dataIn,
ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes,
int imageSizeInBytes, 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;
int src = 0;
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];
int cc;
-
+
dataIn.position( src );
extract.extract( isSwap, dataIn, extractTotals[0] );
dataIn.position( src + pixelSizeInBytes );
@@ -1506,7 +1506,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
diff --git a/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java b/src/jogl/classes/jogamp/opengl/glu/mipmap/Image.java
index b610ce86b..18f814dde 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
@@ -53,18 +53,18 @@ import java.nio.*;
* @author Administrator
*/
public class Image {
-
+
/** Creates a new instance of Image */
public Image() {
}
-
+
public static short getShortFromByteArray( byte[] array, 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 ) {
int i;
i = ( array[index] << 24 ) & 0xFF000000;
@@ -73,12 +73,12 @@ public class Image {
i |= ( array[index+3] ) & 0x000000FF;
return( i );
}
-
+
public static float getFloatFromByteArray( byte[] array, int index ) {
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.
@@ -98,7 +98,7 @@ public class Image {
int iter2;
int i, j, k;
boolean myswap_bytes;
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
@@ -139,7 +139,7 @@ public class Image {
extract = new Extract2101010rev();
break;
}
-
+
myswap_bytes = psm.getUnpackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getUnpackRowLength() > 0 ) {
@@ -147,12 +147,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 +200,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,7 +208,7 @@ 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;
@@ -364,7 +364,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 +374,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,
+ public static void empty_image( PixelStorageModes psm, int width, int height,
+ int format, int type, boolean index_format,
ShortBuffer oldimage, ByteBuffer userdata ) {
-
+
int components;
int element_size;
int rowsize;
@@ -396,7 +396,7 @@ public class Image {
int iter2;
int i, j, k;
boolean myswap_bytes;
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
@@ -437,7 +437,7 @@ public class Image {
extract = new Extract2101010rev();
break;
}
-
+
myswap_bytes = psm.getPackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getPackRowLength() > 0 ) {
@@ -445,12 +445,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 +472,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 +488,7 @@ public class Image {
userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 7 - bit_offset ) ) ) );
}
}
-
+
bit_offset++;
if( bit_offset == 8 ) {
bit_offset = 0;
@@ -500,13 +500,13 @@ public class Image {
}
} else {
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,13 +514,13 @@ 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();
-
+
switch( type ) {
case( GL2.GL_UNSIGNED_BYTE_3_3_2 ):
for( k = 0; k < 3; k++ ) {
@@ -799,7 +799,7 @@ 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 ) {
@@ -819,7 +819,7 @@ public class Image {
int ww, hh, dd, k;
Type_Widget widget = new Type_Widget();
float extractComponents[] = new float[4];
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
@@ -860,7 +860,7 @@ public class Image {
extract = new Extract2101010rev();
break;
}
-
+
myswapBytes = psm.getUnpackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getUnpackRowLength() > 0 ) {
@@ -873,7 +873,7 @@ public class Image {
if( elementSize == 1 ) {
myswapBytes = false;
}
-
+
// 3dstuff begin
if( psm.getUnpackImageHeight() > 0 ) {
rowsPerImage = psm.getUnpackImageHeight();
@@ -881,27 +881,27 @@ 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 ):
if( indexFormat ) {
@@ -1063,18 +1063,18 @@ 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 ) {
boolean myswapBytes;
@@ -1092,7 +1092,7 @@ public class Image {
int imageSize;
Type_Widget widget = new Type_Widget();
float[] shoveComponents = new float[4];
-
+
// Create a Extract interface object
Extract extract = null;
switch( type ) {
@@ -1133,9 +1133,9 @@ public class Image {
extract = new Extract2101010rev();
break;
}
-
+
iter = 0;
-
+
myswapBytes = psm.getPackSwapBytes();
components = Mipmap.elements_per_group( format, type );
if( psm.getPackRowLength() > 0 ) {
@@ -1143,44 +1143,44 @@ 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 ):
if( indexFormat ) {
@@ -1392,20 +1392,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..938873ec5 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
@@ -57,11 +57,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 +79,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 +99,7 @@ public class Mipmap {
i *= 2;
}
}
-
+
public static short GLU_SWAP_2_BYTES( short s ) {
byte b = 0;
b = (byte)( s >>> 8 );
@@ -107,7 +107,7 @@ public class Mipmap {
s = (short)( s | (0x00FF & b) );
return( s );
}
-
+
public static int GLU_SWAP_4_BYTES( int i ) {
int t = i << 24;
t |= 0x00FF0000 & ( i << 8 );
@@ -115,13 +115,13 @@ public class Mipmap {
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 );
return( temp );
}
-
+
public static int checkMipmapArgs( int internalFormat, int format, int type ) {
if( !legalFormat( format ) || !legalType( type ) ) {
return( GLU.GLU_INVALID_ENUM );
@@ -134,7 +134,7 @@ public class Mipmap {
}
return( 0 );
}
-
+
public static boolean legalFormat( int format ) {
switch( format ) {
case( GL2.GL_COLOR_INDEX ):
@@ -155,7 +155,7 @@ public class Mipmap {
return( false );
}
}
-
+
public static boolean legalType( int type ) {
switch( type ) {
case( GL2.GL_BITMAP ):
@@ -183,10 +183,10 @@ public class Mipmap {
return( false );
}
}
-
+
public static boolean isTypePackedPixel( 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 ||
@@ -203,20 +203,20 @@ public class Mipmap {
}
return( false );
}
-
+
public static boolean isLegalFormatForPackedPixelType( int format, 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 ) {
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 ||
@@ -232,7 +232,7 @@ public class Mipmap {
}
return( true );
}
-
+
public static boolean isLegalLevels( int userLevel, int baseLevel, int maxLevel,
int totalLevels ) {
if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) ||
@@ -241,7 +241,7 @@ public class Mipmap {
}
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 ).
@@ -257,7 +257,7 @@ public class Mipmap {
int heightPowerOf2 = nearestPower( height );
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
@@ -268,20 +268,20 @@ public class Mipmap {
int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 );
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 ) {
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) ||
+ } 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) ) {
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP;
gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne,
@@ -289,7 +289,7 @@ public class Mipmap {
} 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()) {
@@ -336,15 +336,15 @@ public class Mipmap {
newHeight[0] = maxsize[0];
}
}
-
- public static void closestFit3D( GL gl, int target, int width, int height, int depth,
+
+ 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 ) {
int widthPowerOf2 = nearestPower( width );
int heightPowerOf2 = nearestPower( height );
int depthPowerOf2 = nearestPower( depth );
int[] proxyWidth = new int[1];
-
+
do {
// compute level 1 width & height & depth, clamping each at 1
int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2;
@@ -354,7 +354,7 @@ public class Mipmap {
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 ) {
proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D;
@@ -378,16 +378,16 @@ 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 ) {
// 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 ||
@@ -403,7 +403,7 @@ public class Mipmap {
type == GL2GL3.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 ):
@@ -418,10 +418,10 @@ public class Mipmap {
return( 1 );
}
}
-
+
public static int bytes_per_element( int type ) {
// return the number of bytes per element, based on the element type
-
+
switch( type ) {
case( GL2.GL_BITMAP ):
case( GL2GL3.GL_BYTE ):
@@ -450,17 +450,17 @@ public class Mipmap {
return( 4 );
}
}
-
+
public static boolean is_index( int format ) {
return( format == GL2.GL_COLOR_INDEX || format == GL2GL3.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 ) {
int bytes_per_row;
int components;
-
+
assert( width > 0 );
assert( height > 0 );
components = elements_per_group( format, type );
@@ -471,17 +471,17 @@ 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;
-
+
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);
@@ -496,7 +496,7 @@ public class Mipmap {
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);
psm.setPackAlignment( a[0] );
gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
@@ -510,7 +510,7 @@ public class Mipmap {
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);
@@ -529,7 +529,7 @@ public class Mipmap {
psm.setUnpackSkipImages( a[0] );
gl.glGetIntegerv( GL2GL3.GL_UNPACK_IMAGE_HEIGHT, a, 0);
psm.setUnpackImageHeight( a[0] );
-
+
gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0);
psm.setPackAlignment( a[0] );
gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0);
@@ -547,9 +547,9 @@ 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,
+
+ 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();
@@ -559,7 +559,7 @@ public class Mipmap {
ByteBuffer beforeimage;
ByteBuffer afterimage;
PixelStorageModes psm = new PixelStorageModes();
-
+
if( (widthin == 0) || (heightin == 0) || (widthout == 0) || (heightout == 0) ) {
return( 0 );
}
@@ -580,20 +580,20 @@ public class Mipmap {
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 ) {
@@ -601,30 +601,30 @@ public class Mipmap {
try {
int levels;
-
+
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();
@@ -633,54 +633,54 @@ public class Mipmap {
int[] widthPowerOf2 = new int[1];
int levels;
int[] dummy = new int[1];
-
+
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;
int level, levels;
-
+
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;
if( data instanceof ByteBuffer ) {
@@ -706,7 +706,7 @@ public class Mipmap {
FloatBuffer fb = buffer.asFloatBuffer();
fb.put( array );
}
-
+
try {
return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat,
width, height, width, height, format, type, userLevel, baseLevel,
@@ -716,7 +716,7 @@ 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;
@@ -724,25 +724,25 @@ public class Mipmap {
int[] widthPowerOf2 = new int[1];
int[] heightPowerOf2 = new int[1];
int level, levels;
-
+
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;
if( data instanceof ByteBuffer ) {
@@ -768,17 +768,17 @@ public class Mipmap {
FloatBuffer fb = buffer.asFloatBuffer();
fb.put( array );
}
-
+
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();
@@ -788,23 +788,23 @@ public class Mipmap {
int[] heightPowerOf2 = new int[1];
int[] depthPowerOf2 = new int[1];
int level, levels;
-
+
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 +814,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 +822,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();
try {
int level, levels;
-
+
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 +852,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..7eb98db35 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() {
}
@@ -421,6 +421,6 @@ public class PixelStorageModes {
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..9aca1fb03 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,9 +55,9 @@ 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 ) {
float x, lowx, highx, convx, halfconvx;
@@ -69,7 +69,7 @@ public class ScaleInternal {
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,9 +146,9 @@ public class ScaleInternal {
}
}
}
-
+
public static void scale_internal_ubyte( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
+ ByteBuffer datain, int widthout, int heightout,
ByteBuffer dataout, int element_size, int ysize, int group_size ) {
float x, convx;
float y, convy;
@@ -157,11 +157,11 @@ public class ScaleInternal {
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 +169,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 +181,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 +239,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 +261,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 +339,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -364,9 +371,9 @@ public class ScaleInternal {
}
}
}
-
+
public static void scale_internal_byte( int components, int widthin, int heightin,
- ByteBuffer datain, int widthout, int heightout,
+ ByteBuffer datain, int widthout, int heightout,
ByteBuffer dataout, int element_size, int ysize,
int group_size ) {
float x, convx;
@@ -376,11 +383,11 @@ public class ScaleInternal {
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 +395,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 +407,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 +464,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 +486,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 +550,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 +564,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -582,10 +596,10 @@ 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,
+ 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;
@@ -594,11 +608,11 @@ public class ScaleInternal {
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 +620,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,34 +632,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 );
@@ -680,7 +701,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 +735,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 +834,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 +852,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -863,10 +884,10 @@ 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,
+ ShortBuffer dataout, int element_size, int ysize,
int group_size, boolean myswap_bytes ) {
float x, convx;
float y, convy;
@@ -875,11 +896,11 @@ public class ScaleInternal {
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 +908,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 +922,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 +994,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 +1031,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 +1137,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 +1156,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -1160,10 +1188,10 @@ 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,
+ 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;
@@ -1172,11 +1200,11 @@ public class ScaleInternal {
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 +1212,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 +1224,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 +1293,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 +1327,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;
@@ -1392,7 +1427,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 +1445,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
float value = 0.0f;
for( k = 0; k < components; k++ ) {
@@ -1448,10 +1483,10 @@ 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,
+ 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;
@@ -1460,11 +1495,11 @@ public class ScaleInternal {
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 +1507,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 +1521,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 +1593,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 +1630,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 +1736,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 +1755,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -1745,10 +1787,10 @@ 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,
+ 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;
@@ -1757,11 +1799,11 @@ public class ScaleInternal {
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 +1811,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 +1825,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 +1897,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 +1934,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 +2040,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 +2059,7 @@ public class ScaleInternal {
}
temp0 += ysize;
}
-
+
outindex = ( j + ( i * widthout ) ) * components;
for( k = 0; k < components; k++ ) {
dataout.position( outindex + k );
@@ -2042,28 +2091,28 @@ public class ScaleInternal {
}
}
}
-
- public static void scaleInternalPackedPixel( int components, Extract extract,
+
+ 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;
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];
-
+
float area;
int i, j, k, xindex;
-
+
int temp, temp0;
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 +2120,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 +2132,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 +2148,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 +2184,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 +2207,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 +2277,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 +2292,7 @@ public class ScaleInternal {
}
temp0 += rowSizeInBytes;
}
-
+
outIndex = ( j + ( i * widthOut ) );
for( k = 0; k < components; k++ ) {
shoveTotals[k] = totals[k] / area;
@@ -2276,7 +2325,7 @@ 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 ) {
@@ -2290,9 +2339,9 @@ public class ScaleInternal {
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 +2375,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 +2391,7 @@ public class ScaleInternal {
} else {
zpercent = zint + 1 - z;
}
-
+
y = lowy;
yint = (int)(Math.floor( y ) );
while( y < highy ) {
@@ -2352,10 +2401,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 +2412,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 +2430,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 +2441,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,
+
+ 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 ) {
int components;
ShortBuffer beforeImage, afterImage;
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,
+ beforeImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
- afterImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
+ afterImage = Buffers.newDirectByteBuffer( Mipmap.imageSize3D( widthIn,
heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) ).asShortBuffer();
} catch( 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 +2490,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..dc401880d 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 ) {
buffer.position( 0 );
buffer.put( b );
}
-
+
public byte getUB0() {
buffer.position( 0 );
return( buffer.get() );
}
-
+
public void setUB1( byte b ) {
buffer.position( 1 );
buffer.put( b );
}
-
+
public byte getUB1() {
buffer.position( 1 );
return( buffer.get() );
}
-
+
public void setUB2( byte b ) {
buffer.position( 2 );
buffer.put( b );
}
-
+
public byte getUB2() {
buffer.position( 2 );
return( buffer.get() );
}
-
+
public void setUB3( byte b ) {
buffer.position( 3 );
buffer.put( b );
}
-
+
public byte getUB3() {
buffer.position( 3 );
return( buffer.get() );
}
-
+
public void setUS0( short s ) {
buffer.position( 0 );
buffer.putShort( s );
}
-
+
public short getUS0() {
buffer.position( 0 );
return( buffer.getShort() );
}
-
+
public void setUS1( short s ) {
buffer.position( 2 );
buffer.putShort( s );
}
-
+
public short getUS1() {
buffer.position( 2 );
return( buffer.getShort() );
}
-
+
public void setUI( int i ) {
buffer.position( 0 );
buffer.putInt( i );
}
-
+
public int getUI() {
buffer.position( 0 );
return( buffer.getInt() );
}
-
+
public void setB0( byte b ) {
buffer.position( 0 );
buffer.put( b );
}
-
+
public byte getB0() {
buffer.position( 0 );
return( buffer.get() );
}
-
+
public void setB1( byte b ) {
buffer.position( 1 );
buffer.put( b );
}
-
+
public byte getB1() {
buffer.position( 1 );
return( buffer.get() );
}
-
+
public void setB2( byte b ) {
buffer.position( 2 );
buffer.put( b );
}
-
+
public byte getB2() {
buffer.position( 2 );
return( buffer.get() );
}
-
+
public void setB3( byte b ) {
buffer.position( 3 );
buffer.put( b );
}
-
+
public byte getB3() {
buffer.position( 3 );
return( buffer.get() );
}
-
+
public void setS0( short s ) {
buffer.position( 0 );
buffer.putShort( s );
}
-
+
public short getS0() {
buffer.position( 0 );
return( buffer.getShort() );
}
-
+
public void setS1( short s ) {
buffer.position( 2 );
buffer.putShort( s );
}
-
+
public short getS1() {
buffer.position( 2 );
return( buffer.getShort() );
}
-
+
public void setI( int i ) {
buffer.position( 0 );
buffer.putInt( i );
}
-
+
public int getI() {
buffer.position( 0 );
return( buffer.getInt() );
}
-
+
public void setF( 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();
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..df2b9a147 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Arc.java
@@ -72,7 +72,7 @@ public class Arc {
/**
* Makes new arc at specified side
- *
+ *
* @param side
* which side doeas this arc form
*/
@@ -86,7 +86,7 @@ public class Arc {
/**
* Sets side the arc is at
- *
+ *
* @param side
* arc side
*/
@@ -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,7 +147,7 @@ public class Arc {
/**
* Appends arc to the list
- *
+ *
* @param jarc
* arc to be append
* @return this
@@ -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..c299b10af 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcSdirSorter.java
@@ -44,7 +44,7 @@ public class ArcSdirSorter {
/**
* Makes new ArcSdirSorter with Subdivider
* @param subdivider subdivider
- */
+ */
public ArcSdirSorter(Subdivider subdivider) {
//TODO
// System.out.println("TODO arcsdirsorter.constructor");
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
index be72c53d2..1a584c396 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/ArcTdirSorter.java
@@ -43,7 +43,7 @@ public class ArcTdirSorter {
/**
* Makes new ArcSdirSorter with Subdivider
* @param subdivider subdivider
- */
+ */
public ArcTdirSorter(Subdivider subdivider) {
// TODO Auto-generated constructor stub
// System.out.println("TODO arcTsorter.konstruktor");
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Backend.java
index 610a19556..3e974247b 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();
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
index df8b16ab5..17437ef01 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Bin.java
@@ -143,7 +143,7 @@ public class Bin {
/**
* Returns next arc in linked list
* @return next arc
- *
+ *
*/
private Arc nextarc() {
// DONE
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..b67764c30 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 {
/**
@@ -24,7 +24,7 @@ public class CArrayOfArcs {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
@@ -38,7 +38,7 @@ public class CArrayOfArcs {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
@@ -50,7 +50,7 @@ public class CArrayOfArcs {
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param ctlarray
* underlaying array
*/
@@ -61,7 +61,7 @@ public class CArrayOfArcs {
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Arc get() {
@@ -78,7 +78,7 @@ public class CArrayOfArcs {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
@@ -89,7 +89,7 @@ public class CArrayOfArcs {
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
@@ -100,7 +100,7 @@ public class CArrayOfArcs {
/**
* Returns array element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @return element at relative index
@@ -111,7 +111,7 @@ public class CArrayOfArcs {
/**
* Sets value of element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @param value
@@ -123,7 +123,7 @@ public class CArrayOfArcs {
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
@@ -134,7 +134,7 @@ public class CArrayOfArcs {
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -143,7 +143,7 @@ public class CArrayOfArcs {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
@@ -156,7 +156,7 @@ public class CArrayOfArcs {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
@@ -175,7 +175,7 @@ public class CArrayOfArcs {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public Arc[] getArray() {
@@ -184,7 +184,7 @@ public class CArrayOfArcs {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying 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..b5f588960 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfBreakpts.java
@@ -2,9 +2,9 @@ package jogamp.opengl.glu.nurbs;
/**
* Class replacing C language pointer
- *
+ *
* @author Tomas Hrasky
- *
+ *
*/
public class CArrayOfBreakpts {
/**
@@ -19,7 +19,7 @@ public class CArrayOfBreakpts {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
@@ -32,7 +32,7 @@ public class CArrayOfBreakpts {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
@@ -43,7 +43,7 @@ public class CArrayOfBreakpts {
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Breakpt get() {
@@ -59,7 +59,7 @@ public class CArrayOfBreakpts {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
@@ -70,7 +70,7 @@ public class CArrayOfBreakpts {
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
@@ -81,7 +81,7 @@ public class CArrayOfBreakpts {
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
@@ -92,7 +92,7 @@ public class CArrayOfBreakpts {
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -101,7 +101,7 @@ public class CArrayOfBreakpts {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
@@ -111,7 +111,7 @@ public class CArrayOfBreakpts {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/CArrayOfFloats.java
index 39ef841ec..d9e4d0ff1 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 {
@@ -25,7 +25,7 @@ public class CArrayOfFloats {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
@@ -39,7 +39,7 @@ public class CArrayOfFloats {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
@@ -51,7 +51,7 @@ public class CArrayOfFloats {
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param ctlarray
* underlaying array
*/
@@ -62,7 +62,7 @@ public class CArrayOfFloats {
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public float get() {
@@ -79,7 +79,7 @@ public class CArrayOfFloats {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
@@ -90,7 +90,7 @@ public class CArrayOfFloats {
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
@@ -101,7 +101,7 @@ public class CArrayOfFloats {
/**
* Returns array element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @return element at relative index
@@ -112,7 +112,7 @@ public class CArrayOfFloats {
/**
* Sets value of element at specified index relatively to pointer
- *
+ *
* @param i
* relative index
* @param value
@@ -124,7 +124,7 @@ public class CArrayOfFloats {
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
@@ -135,7 +135,7 @@ public class CArrayOfFloats {
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -144,7 +144,7 @@ public class CArrayOfFloats {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
@@ -157,7 +157,7 @@ public class CArrayOfFloats {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
@@ -176,7 +176,7 @@ public class CArrayOfFloats {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public float[] getArray() {
@@ -185,7 +185,7 @@ public class CArrayOfFloats {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying 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..e7bbac16a 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,7 +19,7 @@ public class CArrayOfQuiltspecs {
/**
* Makes new CArray
- *
+ *
* @param array
* underlaying array
* @param pointer
@@ -32,7 +32,7 @@ public class CArrayOfQuiltspecs {
/**
* Makes new CArray from other CArray
- *
+ *
* @param carray
* reference array
*/
@@ -43,7 +43,7 @@ public class CArrayOfQuiltspecs {
/**
* Makes new CArray with pointer set to 0
- *
+ *
* @param array
* underlaying array
*/
@@ -54,7 +54,7 @@ public class CArrayOfQuiltspecs {
/**
* Returns element at pointer
- *
+ *
* @return element at pointer
*/
public Quiltspec get() {
@@ -70,7 +70,7 @@ public class CArrayOfQuiltspecs {
/**
* Sets element at pointer
- *
+ *
* @param f
* desired value
*/
@@ -81,7 +81,7 @@ public class CArrayOfQuiltspecs {
/**
* Returns array element at specified index
- *
+ *
* @param i
* array index
* @return element at index
@@ -92,7 +92,7 @@ public class CArrayOfQuiltspecs {
/**
* Lessens pointer by value
- *
+ *
* @param i
* lessen by
*/
@@ -103,7 +103,7 @@ public class CArrayOfQuiltspecs {
/**
* Returns pointer value
- *
+ *
* @return pointer value
*/
public int getPointer() {
@@ -112,7 +112,7 @@ public class CArrayOfQuiltspecs {
/**
* Sets ponter value
- *
+ *
* @param pointer
* pointer value to be set
*/
@@ -122,7 +122,7 @@ public class CArrayOfQuiltspecs {
/**
* Raises pointer by value
- *
+ *
* @param i
* raise by
*/
@@ -141,7 +141,7 @@ public class CArrayOfQuiltspecs {
/**
* Returns underlaying array
- *
+ *
* @return underlaying array
*/
public Quiltspec[] getArray() {
@@ -150,7 +150,7 @@ public class CArrayOfQuiltspecs {
/**
* Sets underlaying array
- *
+ *
* @param array
* underlaying 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..ea3a3d14e 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Curve.java
@@ -103,7 +103,7 @@ public class Curve {
/**
* Makes new Curve
- *
+ *
* @param geo
* @param pta
* @param ptb
@@ -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);
@@ -229,7 +229,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/Flist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Flist.java
index 6983691d9..f9c4c2d6f 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;
@@ -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
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Knotspec.java
index 114832a1c..1dcf393a9 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 {
@@ -314,7 +314,7 @@ public class Knotspec {
/**
* Copies control points
- *
+ *
* @param _inpt
* input control points
* @param _outpt
@@ -346,7 +346,7 @@ public class Knotspec {
/**
* Copies one control point to other
- *
+ *
* @param topt
* source control point
* @param frompt
@@ -374,7 +374,7 @@ public class Knotspec {
/**
* Inserts a knot
- *
+ *
* @param _p
* inserted knot
*/
@@ -402,7 +402,7 @@ public class Knotspec {
}
}
- } else {//code for curve
+ } else {//code for curve
if (this.equals(kspectotrans)) {
insert(p);
} else {
@@ -428,7 +428,7 @@ public class Knotspec {
/**
* Inserts a knot and computes new control points
- *
+ *
* @param p
* inserted knot
*/
@@ -490,7 +490,7 @@ public class Knotspec {
/**
* Copies one control point to another
- *
+ *
* @param topt
* source ctrl point
* @param frompt
@@ -519,7 +519,7 @@ public class Knotspec {
/**
* Computes new control point
- *
+ *
* @param x
* first point
* @param y
@@ -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..571f44f06 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
@@ -92,7 +92,7 @@ public class Knotvector {
/**
* Initializes knotvector
- *
+ *
* @param nknots
* number of knots
* @param stride
@@ -116,7 +116,7 @@ public class Knotvector {
/**
* Validates knot vector parameters
- *
+ *
* @return knot vector validity
*/
public int validate() {
@@ -154,7 +154,7 @@ public class Knotvector {
/**
* Show specified message
- *
+ *
* @param msg
* message to be shown
*/
@@ -166,7 +166,7 @@ public class Knotvector {
/**
* Compares two knots for equality
- *
+ *
* @param a
* first knot
* @param b
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
index bd5d2db98..86638a827 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Mapdesc.java
@@ -112,7 +112,7 @@ public class Mapdesc {
float clampfactor;
/**
- * Value of N_MINSAVINGS property
+ * Value of N_MINSAVINGS property
*/
private float minsavings;
@@ -162,7 +162,7 @@ public class Mapdesc {
private float[] bboxsize;
/**
- * Makes new mapdesc
+ * Makes new mapdesc
* @param type map type
* @param rational is rational
* @param ncoords number of control points coords
@@ -318,7 +318,7 @@ public class Mapdesc {
}
/**
- * Tells whether map is culling
+ * Tells whether map is culling
* @return is map culling
*/
public boolean isCulling() {
@@ -327,7 +327,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 +335,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,7 +343,7 @@ public class Mapdesc {
}
/**
- * Returns property of specified tag value
+ * Returns property of specified tag value
* @param tag property tag
* @return property value
*/
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..a686da696 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/O_nurbscurve.java
@@ -68,7 +68,7 @@ public class O_nurbscurve {
/**
* Makes new O_nurbscurve
- * @param realType type of curve
+ * @param realType type of curve
*/
public O_nurbscurve(int realType) {
// DONE
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
index f1e499a28..8c2922565 100644
--- a/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
+++ b/src/jogl/classes/jogamp/opengl/glu/nurbs/Patchlist.java
@@ -52,7 +52,7 @@ 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
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Property.java
index 25b4dc441..79f36ce43 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
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Renderhints.java
index 4729e2421..7c636122f 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
*
*/
diff --git a/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java b/src/jogl/classes/jogamp/opengl/glu/nurbs/Subdivider.java
index 37774f811..4d8296cca 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;
@@ -375,7 +375,7 @@ public class Subdivider {
}
/**
- * Sample
+ * Sample
* @param source
* @param patchlist
* @param subdivisions
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..9c8523e51 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,11 +51,11 @@ 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) {
if( name == GLU.GLU_VERSION ) {
return( "1.3" );
@@ -64,7 +64,7 @@ public class Registry {
}
return( null );
}
-
+
public static boolean gluCheckExtension( String extName, String extString ) {
if( extName == null || extString == null ) {
return( false );
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
index 474056cc3..1ac0fd438 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQHeap.java
@@ -81,6 +81,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapDeletePriorityQ */
+ @Override
void pqDeletePriorityQ() {
handles = null;
nodes = null;
@@ -137,6 +138,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapInit */
+ @Override
boolean pqInit() {
int i;
@@ -152,6 +154,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
/* really __gl_pqHeapInsert */
/* returns LONG_MAX iff out of memory */
+ @Override
int pqInsert(Object keyNew) {
int curr;
int free;
@@ -207,6 +210,7 @@ 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;
@@ -229,6 +233,7 @@ class PriorityQHeap extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqHeapDelete */
+ @Override
void pqDelete(int hCurr) {
jogamp.opengl.glu.tessellator.PriorityQ.PQnode[] n = nodes;
jogamp.opengl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles;
@@ -252,10 +257,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..cf54b15c3 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/PriorityQSort.java
@@ -71,6 +71,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortDeletePriorityQ */
+ @Override
void pqDeletePriorityQ() {
if (heap != null) heap.pqDeletePriorityQ();
order = null;
@@ -100,6 +101,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortInit */
+ @Override
boolean pqInit() {
int p, r, i, j;
int piv;
@@ -191,6 +193,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
/* really __gl_pqSortInsert */
/* returns LONG_MAX iff out of memory */
+ @Override
int pqInsert(Object keyNew) {
int curr;
@@ -220,6 +223,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortExtractMin */
+ @Override
Object pqExtractMin() {
Object sortMin, heapMin;
@@ -240,6 +244,7 @@ class PriorityQSort extends jogamp.opengl.glu.tessellator.PriorityQ {
}
/* really __gl_pqSortMinimum */
+ @Override
Object pqMinimum() {
Object sortMin, heapMin;
@@ -257,11 +262,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..a2e973508 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Render.java
@@ -279,6 +279,7 @@ class Render {
}
private static class RenderTriangle implements renderCallBack {
+ @Override
public void render(GLUtessellatorImpl tess, jogamp.opengl.glu.tessellator.GLUhalfEdge e, long size) {
/* Just add the triangle to a triangle list, so we can render all
* the separate triangles at once.
@@ -323,6 +324,7 @@ class Render {
}
private static class RenderFan implements renderCallBack {
+ @Override
public void render(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
@@ -345,6 +347,7 @@ class Render {
}
private static class RenderStrip implements renderCallBack {
+ @Override
public void render(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
diff --git a/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java b/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
index b4a400c1c..d2c0db61e 100644
--- a/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
+++ b/src/jogl/classes/jogamp/opengl/glu/tessellator/Sweep.java
@@ -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();
@@ -1150,6 +1150,7 @@ class Sweep {
*/ {
/* __gl_dictListNewDict */
tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() {
+ @Override
public boolean leq(Object frame, Object key1, Object key2) {
return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2);
}
@@ -1231,6 +1232,7 @@ class Sweep {
/* __gl_pqSortNewPriorityQ */
pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() {
+ @Override
public boolean leq(Object key1, Object key2) {
return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2);
}
@@ -1240,7 +1242,7 @@ class Sweep {
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 */
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 3cd4b340c..259c70641 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.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.opengl.macosx.cgl;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.Map;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -48,110 +49,180 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
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 jogamp.nativewindow.macosx.OSXUtil;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;
+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.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)
protected interface GLBackendImpl {
boolean isNSContext();
long create(long share, int ctp, int major, int minor);
boolean destroy(long ctx);
+ void associateDrawable(boolean bound);
boolean copyImpl(long src, int mask);
boolean makeCurrent(long ctx);
boolean release(long ctx);
+ boolean detachPBuffer();
boolean setSwapInterval(int interval);
boolean swapBuffers();
}
-
+
/* 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 ) ;
-
+
// 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(AbstractGraphicsDevice device, int ctp, int major, 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(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(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(PMVMatrix.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;
-
+
// Implementation object (either NSOpenGL-based or CGL-based)
protected GLBackendImpl impl;
-
+
private CGLExt _cglExt;
// Table that holds the addresses of the native C-language entry points for
// CGL extension functions.
private CGLExtProcAddressTable cglExtProcAddressTable;
-
+
+ private long updateHandle = 0;
+ private int lastWidth, lastHeight;
+
protected MacOSXCGLContext(GLDrawableImpl drawable,
GLContext shareWith) {
super(drawable, shareWith);
initOpenGLImpl(getOpenGLMode());
}
-
+
@Override
- protected void resetStates() {
+ protected void resetStates(boolean isInit) {
// no inner state _cglExt = null;
cglExtProcAddressTable = null;
- super.resetStates();
+ super.resetStates(isInit);
}
+ @Override
public Object getPlatformGLExtensions() {
return getCGLExt();
}
- protected boolean isNSContext() {
- return (null != impl) ? impl.isNSContext() : this.openGLMode == GLBackendType.NSOPENGL;
+ protected boolean isNSContext() {
+ return (null != impl) ? impl.isNSContext() : this.openGLMode == GLBackendType.NSOPENGL;
}
public CGLExt getCGLExt() {
@@ -161,6 +232,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return _cglExt;
}
+ @Override
public final ProcAddressTable getPlatformExtProcAddressTable() {
return getCGLExtProcAddressTable();
}
@@ -169,10 +241,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return cglExtProcAddressTable;
}
+ @Override
protected Map<String, String> getFunctionNameMap() { return null; }
+ @Override
protected Map<String, String> getExtensionNameMap() { return null; }
+ @Override
protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
if(!isGLProfileSupported(ctp, major, minor)) {
if(DEBUG) {
@@ -200,69 +275,130 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return ctx;
}
+ @Override
protected void destroyContextARBImpl(long _context) {
impl.release(_context);
impl.destroy(_context);
}
+ @Override
public final boolean isGLReadDrawableAvailable() {
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;
- }
-
- 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
protected void releaseImpl() throws GLException {
if (!impl.release(contextHandle)) {
throw new GLException("Error releasing OpenGL Context: "+this);
}
}
+ @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.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 void associateDrawable(boolean bound) {
+ // context stuff depends on drawable stuff
+ if(bound) {
+ super.associateDrawable(true); // 1) init drawable stuff
+ impl.associateDrawable(true); // 2) init context stuff
+ getUpdateHandle();
+ } else {
+ releaseUpdateHandle();
+ impl.associateDrawable(false); // 1) free context stuff
+ super.associateDrawable(false); // 2) free drawable stuff
+ }
+ }
+
+ /* pp */ void detachPBuffer() {
+ impl.detachPBuffer();
+ }
+
+
+ @Override
protected void copyImpl(GLContext source, int mask) throws GLException {
if( isNSContext() != ((MacOSXCGLContext)source).isNSContext() ) {
throw new GLException("Source/Destination OpenGL Context tyoe mismatch: source "+source+", dest: "+this);
@@ -275,7 +411,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
protected void swapBuffers() {
// single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
if(!impl.swapBuffers()) {
- throw new GLException("Error swapping buffers: "+this);
+ throw new GLException("Error swapping buffers: "+this);
}
}
@@ -284,11 +420,19 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return impl.setSwapInterval(interval);
}
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
+ @Override
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, 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(ByteBuffer pointer) {
// FIXME: apparently the Apple extension doesn't require a custom memory allocator
throw new GLException("Not yet implemented");
}
+ @Override
protected final void updateGLXProcAddressTable() {
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
@@ -316,39 +460,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
}
}
-
+
+ @Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
return new StringBuilder();
}
-
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_ARB_pixel_format")) {
- return true;
- }
- return super.isExtensionAvailable(glExtensionName);
- }
-
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
- }
-
// Support for "mode switching" as described in MacOSXCGLDrawable
public void setOpenGLMode(GLBackendType mode) {
if (mode == openGLMode) {
@@ -364,10 +481,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
initOpenGLImpl(mode);
openGLMode = mode;
- haveSetOpenGLMode = true;
+ haveSetOpenGLMode = true;
}
public final GLBackendType getOpenGLMode() { return openGLMode; }
-
+
protected void initOpenGLImpl(GLBackendType backend) {
switch (backend) {
case NSOPENGL:
@@ -379,8 +496,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
default:
throw new InternalError("Illegal implementation mode " + backend);
}
- }
-
+ }
+
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
@@ -391,291 +509,736 @@ public abstract class MacOSXCGLContext extends GLContextImpl
sb.append("] ");
return sb.toString();
}
-
+
// NSOpenGLContext-based implementation
class NSOpenGLImpl implements GLBackendImpl {
- long nsOpenGLLayer = 0;
- long nsOpenGLLayerPFmt = 0;
- float screenVSyncTimeout; // microSec
- int vsyncTimeout; // microSec - for nsOpenGLLayer mode
-
- public boolean isNSContext() { return true; }
-
- public long create(long share, int ctp, int major, int minor) {
- long ctx = 0;
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) MacOSXCGLContext.this.drawable;
- final NativeSurface surface = drawable.getNativeSurface();
- final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration();
- final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor);
- if (pixelFormat == 0) {
+ private OffscreenLayerSurface backingLayerHost = null;
+ /** 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 boolean needsSetContextPBuffer = false;
+ private ShaderProgram gl3ShaderProgram = null;
+
+ @Override
+ public boolean isNSContext() { return true; }
+
+
+ /** Only returns a valid NSView. If !NSView, return null and mark either pbuffer and FBO. */
+ private long getNSViewHandle(boolean[] isPBuffer, boolean[] isFBO) {
+ final long nsViewHandle;
+ if(drawable instanceof GLFBODrawableImpl) {
+ nsViewHandle = 0;
+ isPBuffer[0] = false;
+ isFBO[0] = true;
+ if(DEBUG) {
+ System.err.println("NS viewHandle.1: GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ } else {
+ final long drawableHandle = drawable.getHandle();
+ final boolean isNSView = OSXUtil.isNSView(drawableHandle);
+ final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle);
+ isPBuffer[0] = CGL.isNSOpenGLPixelBuffer(drawableHandle);
+ isFBO[0] = false;
+
+ if( isNSView ) {
+ nsViewHandle = drawableHandle;
+ } else if( isNSWindow ) {
+ nsViewHandle = OSXUtil.GetNSView(drawableHandle);
+ } else if( isPBuffer[0] ) {
+ nsViewHandle = 0;
+ } else {
+ 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(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();
+ final long nsViewHandle;
+ final boolean isPBuffer;
+ final boolean isFBO;
+ {
+ boolean[] _isPBuffer = { false };
+ boolean[] _isFBO = { false };
+ nsViewHandle = getNSViewHandle(_isPBuffer, _isFBO);
+ isPBuffer = _isPBuffer[0];
+ isFBO = _isFBO[0];
+ }
+ 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 );
+ }
+ {
+ 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;
+ }
+ 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("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps);
+ 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);
+ System.err.println("NS create drawable type: "+drawable.getClass().getName());
+ System.err.println("NS create drawable handle: isPBuffer "+isPBuffer+", isFBO "+isFBO);
+ System.err.println("NS create pixelFormat: "+toHexString(pixelFormat));
+ System.err.println("NS create chosenCaps: "+chosenCaps);
+ System.err.println("NS create fixedCaps: "+fixedCaps);
+ System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle()));
+ System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle));
+ System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
+ // Thread.dumpStack();
}
- return 0;
- }
- config.setChosenPixelFormat(pixelFormat);
- int sRefreshRate = CGL.getScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
- screenVSyncTimeout = 1000000f / (float)sRefreshRate;
- if(DEBUG) {
- System.err.println("NS create OSX>=lion "+isLionOrLater);
- System.err.println("NS create backendType: "+drawable.getOpenGLMode());
- System.err.println("NS create backingLayerHost: "+backingLayerHost);
- System.err.println("NS create share: "+share);
- System.err.println("NS create chosenCaps: "+chosenCaps);
- System.err.println("NS create pixelFormat: "+toHexString(pixelFormat));
- System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle()));
- System.err.println("NS create drawable NSView-handle: "+toHexString(drawable.getNSViewHandle()));
- System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros");
- // Thread.dumpStack();
- }
- try {
- int[] viewNotReady = new int[1];
+ config.setChosenCapabilities(fixedCaps);
+
+ final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
// Try to allocate a context with this
- ctx = CGL.createContext(share,
- drawable.getNSViewHandle(), null!=backingLayerHost,
- pixelFormat,
- chosenCaps.isBackgroundOpaque(),
- viewNotReady, 0);
+ ctx = CGL.createContext(share, nsViewHandle, incompleteView,
+ pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady);
if (0 == ctx) {
- if(DEBUG) {
- System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0]));
- }
- return 0;
+ if(DEBUG) {
+ System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
+ }
+ return 0;
}
-
- if (!chosenCaps.isPBuffer() && !chosenCaps.isBackgroundOpaque()) {
+
+ if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
// Set the context opacity
CGL.setContextOpacity(ctx, 0);
}
+ return ctx;
+ }
- if(DEBUG) {
- GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(null, pixelFormat);
- System.err.println("NS create pixelformat2GLCaps: "+caps0);
+ @Override
+ public boolean destroy(long ctx) {
+ if(0!=pixelFormat) {
+ CGL.deletePixelFormat(pixelFormat);
+ pixelFormat = 0;
}
- GLCapabilitiesImmutable fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat);
- fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
- config.setChosenCapabilities(fixedCaps);
- if(DEBUG) {
- System.err.println("NS create fixedCaps: "+fixedCaps);
+ 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 width;
+ final int height;
+ /** Synchronized by instance's monitor */
+ long nsOpenGLLayer;
+ /** Synchronized by instance's monitor */
+ boolean valid;
+
+ AttachGLLayerCmd(OffscreenLayerSurface ols, long ctx, int shaderProgram, long pfmt, long pbuffer, int texID, boolean isOpaque, int width, int height) {
+ this.ols = ols;
+ this.ctx = ctx;
+ this.shaderProgram = shaderProgram;
+ this.pfmt = pfmt;
+ this.pbuffer = pbuffer;
+ this.texID = texID;
+ this.isOpaque = isOpaque;
+ this.width = width;
+ this.height = height;
+ this.valid = false;
+ this.nsOpenGLLayer = 0;
}
- if(fixedCaps.isPBuffer()) {
- // Must now associate the pbuffer with our newly-created context
- CGL.setContextPBuffer(ctx, drawable.getHandle());
+
+ public final String contentToString() {
+ return "valid "+valid+", size "+width+"x"+height+", ctx "+toHexString(ctx)+", opaque "+isOpaque+", texID "+texID+", pbuffer "+toHexString(pbuffer)+", nsOpenGLLayer "+toHexString(nsOpenGLLayer);
}
- //
- // handled layered surface
- //
- if(null != backingLayerHost) {
- nsOpenGLLayerPFmt = pixelFormat;
- pixelFormat = 0;
- final int texWidth, texHeight;
- if(drawable instanceof MacOSXPbufferCGLDrawable) {
- final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable;
- texWidth = osxPDrawable.getTextureWidth();
- texHeight = osxPDrawable.getTextureHeight();
- } else {
- texWidth = drawable.getWidth();
- texHeight = drawable.getHeight();
- }
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, drawable.getHandle(), fixedCaps.isBackgroundOpaque(), texWidth, texHeight);
- if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) {
- throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable);
- }
- if (DEBUG) {
- System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", texSize "+texWidth+"x"+texHeight+", "+drawable);
- }
- backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
- setSwapInterval(1); // enabled per default in layered surface
+
+ @Override
+ public final String toString() {
+ return "AttachGLLayerCmd["+contentToString()+"]";
}
- } finally {
- if(0!=pixelFormat) {
- CGL.deletePixelFormat(pixelFormat);
+
+ @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, width, height);
+ 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 (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(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(Throwable t) {
+ System.err.println("Catched 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());
+ }
+ }
}
- return ctx;
- }
-
- public boolean destroy(long ctx) {
- if(0 != nsOpenGLLayer) {
- final NativeSurface surface = drawable.getNativeSurface();
- if (DEBUG) {
- System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer));
- }
- final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- if(null == ols) {
- throw new InternalError("XXX: "+ols);
- }
- CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
- ols.detachSurfaceLayer(nsOpenGLLayer);
- CGL.deletePixelFormat(nsOpenGLLayerPFmt);
- nsOpenGLLayerPFmt = 0;
- nsOpenGLLayer = 0;
}
- return CGL.deleteContext(ctx, true);
- }
- public boolean copyImpl(long src, int mask) {
- CGL.copyContext(contextHandle, src, mask);
- return true;
- }
-
- public boolean makeCurrent(long ctx) {
- final long cglCtx = CGL.getCGLContext(ctx);
- if(0 == cglCtx) {
- throw new InternalError("Null CGLContext for: "+this);
+ @Override
+ public void associateDrawable(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
+ //
+ 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();
+ pbufferHandle = 0;
+ fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() {
+ @Override
+ public void swapBuffers(boolean doubleBuffered) {
+ MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers();
+ } } ) ;
+ } else if( CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
+ texID = 0;
+ pbufferHandle = drawableHandle;
+ if(0 != drawableHandle) { // complete 'validatePBufferConfig(..)' procedure
+ CGL.setContextPBuffer(ctx, pbufferHandle);
+ needsSetContextPBuffer = false;
+ }
+ } else {
+ throw new GLException("BackingLayerHost w/ unknown handle (!FBO, !PBuffer): "+drawable);
+ }
+ lastWidth = drawable.getWidth();
+ lastHeight = drawable.getHeight();
+ if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) {
+ throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable);
+ }
+ if( MacOSXCGLContext.this.isGL3core() ) {
+ if( null == gl3ShaderProgram) {
+ gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3ES3());
+ }
+ gl3ShaderProgramName = gl3ShaderProgram.program();
+ } else {
+ gl3ShaderProgramName = 0;
+ }
+
+ // All CALayer lifecycle ops are deferred on main-thread
+ attachGLLayerCmd = new AttachGLLayerCmd(
+ backingLayerHost, ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID,
+ chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight );
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(true): "+attachGLLayerCmd);
+ }
+ OSXUtil.RunOnMainThread(false, attachGLLayerCmd);
+ } else { // -> null == backingLayerHost
+ lastWidth = drawable.getWidth();
+ lastHeight = drawable.getHeight();
+ boolean[] isPBuffer = { false };
+ boolean[] isFBO = { false };
+ CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
+ }
+ } else { // -> !bound
+ if( null != backingLayerHost ) {
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ attachGLLayerCmd = null;
+ if( null == cmd ) {
+ throw new GLException("Null attachGLLayerCmd: "+drawable);
+ }
+ 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, dCmd);
+ if( null != gl3ShaderProgram ) {
+ gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
+ gl3ShaderProgram = null;
+ }
+ }
+ }
+ }
+ CGL.clearDrawable(contextHandle);
+ backingLayerHost = null;
+ }
}
- int err = CGL.CGLLockContext(cglCtx);
- if(CGL.kCGLNoError == err) {
- return CGL.makeCurrentContext(ctx);
- } else if(DEBUG) {
- System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this);
+
+ private final void validatePBufferConfig(long ctx) {
+ final long drawableHandle = drawable.getHandle();
+ if( needsSetContextPBuffer && 0 != drawableHandle && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) {
+ // Must associate the pbuffer with our newly-created context
+ needsSetContextPBuffer = false;
+ CGL.setContextPBuffer(ctx, drawableHandle);
+ if(DEBUG) {
+ System.err.println("NS.validateDrawableConfig bind pbuffer "+toHexString(drawableHandle)+" -> ctx "+toHexString(ctx));
+ }
+ }
}
- return false;
- }
- public boolean release(long ctx) {
- try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:");
- gle.printStackTrace();
+ /** 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();
+ if( lastWidth != width || lastHeight != height ) {
+ lastWidth = drawable.getWidth();
+ lastHeight = drawable.getHeight();
+ if(DEBUG) {
+ System.err.println("NS.validateDrawableConfig size changed");
+ }
+ return true;
}
+ return false;
}
- final boolean res = CGL.clearCurrentContext(ctx);
- final long cglCtx = CGL.getCGLContext(ctx);
- if(0 == cglCtx) {
- throw new InternalError("Null CGLContext for: "+this);
+
+ @Override
+ public boolean copyImpl(long src, int mask) {
+ CGL.copyContext(contextHandle, src, mask);
+ return true;
}
- final int err = CGL.CGLUnlockContext(cglCtx);
- if(DEBUG && CGL.kCGLNoError != err) {
- System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this);
- }
- return res && CGL.kCGLNoError == err;
- }
- public boolean setSwapInterval(int interval) {
- if(0 != nsOpenGLLayer) {
- CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
- vsyncTimeout = interval * (int)screenVSyncTimeout;
- if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); }
+ @Override
+ public boolean makeCurrent(long ctx) {
+ final long cglCtx = CGL.getCGLContext(ctx);
+ if(0 == cglCtx) {
+ throw new InternalError("Null CGLContext for: "+this);
+ }
+ final int err = CGL.CGLLockContext(cglCtx);
+ if(CGL.kCGLNoError == err) {
+ validatePBufferConfig(ctx); // required to handle pbuffer change ASAP
+ return CGL.makeCurrentContext(ctx);
+ } else if(DEBUG) {
+ System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this);
+ }
+ return false;
}
- CGL.setSwapInterval(contextHandle, interval);
- return true;
- }
-
- public boolean swapBuffers() {
- if( 0 != nsOpenGLLayer ) {
- // 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);
+
+ @Override
+ public boolean release(long ctx) {
+ try {
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
+ } catch (GLException gle) {
+ if(DEBUG) {
+ System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:");
+ gle.printStackTrace();
+ }
+ }
+ final boolean res = CGL.clearCurrentContext(ctx);
+ final long cglCtx = CGL.getCGLContext(ctx);
+ if(0 == cglCtx) {
+ throw new InternalError("Null CGLContext for: "+this);
+ }
+ final int err = CGL.CGLUnlockContext(cglCtx);
+ if(DEBUG && CGL.kCGLNoError != err) {
+ System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this);
+ }
+ return res && CGL.kCGLNoError == err;
+ }
+
+ @Override
+ public boolean detachPBuffer() {
+ needsSetContextPBuffer = true;
+ // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil
+ return true;
}
- if(CGL.flushBuffer(contextHandle)) {
- if(0 != nsOpenGLLayer) {
- // trigger CALayer to update
- CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer);
+
+ @Override
+ public boolean setSwapInterval(int interval) {
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ if(null != cmd) {
+ synchronized(cmd) {
+ if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+ setSwapIntervalImpl(cmd.nsOpenGLLayer, interval);
+ return true;
+ }
+ }
}
+ setSwapIntervalImpl(0, interval);
return true;
}
- return false;
- }
+
+ private void setSwapIntervalImpl(final long l, 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);
+ }
+
+ 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 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).getTextureBuffer(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;
+ }
+ }
+ }
+ return CGL.flushBuffer(contextHandle);
+ }
+
}
class CGLImpl implements GLBackendImpl {
- public boolean isNSContext() { return false; }
-
- public long create(long share, int ctp, int major, int minor) {
- long ctx = 0;
- MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
- long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor);
- if (pixelFormat == 0) {
- throw new GLException("Unable to allocate pixel format with requested GLCapabilities");
- }
- config.setChosenPixelFormat(pixelFormat);
- try {
- // Create new context
- PointerBuffer ctxPB = PointerBuffer.allocateDirect(1);
- if (DEBUG) {
- System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share));
- }
- int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB);
- if (res != CGL.kCGLNoError) {
- throw new GLException("Error code " + res + " while creating context");
+ @Override
+ public boolean isNSContext() { return false; }
+
+ @Override
+ public long create(long share, int ctp, int major, int minor) {
+ long ctx = 0;
+ 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");
}
- if(chosenCaps.isPBuffer()) {
- // Attach newly-created context to the pbuffer
- res = CGL.CGLSetPBuffer(ctxPB.get(0), drawable.getHandle(), 0, 0, 0);
+ try {
+ // Create new context
+ PointerBuffer ctxPB = PointerBuffer.allocateDirect(1);
+ if (DEBUG) {
+ System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share));
+ }
+ int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB);
if (res != CGL.kCGLNoError) {
- throw new GLException("Error code " + res + " while attaching context to pbuffer");
+ throw new GLException("Error code " + res + " while creating context");
}
+ ctx = ctxPB.get(0);
+
+ if (0 != ctx) {
+ GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat);
+ fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque());
+ { // 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);
+ }
+ if(fixedCaps.isPBuffer()) {
+ // Must now associate the pbuffer with our newly-created context
+ res = CGL.CGLSetPBuffer(ctx, drawable.getHandle(), 0, 0, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while attaching context to pbuffer");
+ }
+ }
+ }
+ } finally {
+ CGL.CGLDestroyPixelFormat(pixelFormat);
}
- ctx = ctxPB.get(0);
- if(0!=ctx) {
- if(DEBUG) {
- GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat);
- System.err.println("NS created: "+caps0);
- }
- }
- } finally {
- CGL.CGLDestroyPixelFormat(pixelFormat);
+ return ctx;
}
- return ctx;
- }
-
- public boolean destroy(long ctx) {
- return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError;
- }
- public boolean copyImpl(long src, int mask) {
- CGL.CGLCopyContext(src, contextHandle, mask);
- return true;
- }
-
- public boolean makeCurrent(long ctx) {
- int err = CGL.CGLLockContext(ctx);
- if(CGL.kCGLNoError == err) {
- err = CGL.CGLSetCurrentContext(ctx);
+ @Override
+ public boolean destroy(long ctx) {
+ return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError;
+ }
+
+ @Override
+ public void associateDrawable(boolean bound) {
+ }
+
+ @Override
+ public boolean copyImpl(long src, int mask) {
+ CGL.CGLCopyContext(src, contextHandle, mask);
+ return true;
+ }
+
+ @Override
+ public boolean makeCurrent(long ctx) {
+ int err = CGL.CGLLockContext(ctx);
if(CGL.kCGLNoError == err) {
- return true;
+ err = CGL.CGLSetCurrentContext(ctx);
+ if(CGL.kCGLNoError == err) {
+ return true;
+ } else if(DEBUG) {
+ System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this);
+ }
} else if(DEBUG) {
- System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this);
+ System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this);
}
- } else if(DEBUG) {
- System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this);
+ return false;
}
- return false;
- }
- public boolean release(long ctx) {
- try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:");
- gle.printStackTrace();
+ @Override
+ public boolean release(long ctx) {
+ try {
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
+ } catch (GLException gle) {
+ if(DEBUG) {
+ System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:");
+ gle.printStackTrace();
+ }
}
+ 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);
+ if(DEBUG && CGL.kCGLNoError != err2) {
+ System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this);
+ }
+ return CGL.kCGLNoError == err && CGL.kCGLNoError == err2;
}
- 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);
+
+ @Override
+ public boolean detachPBuffer() {
+ /* Doesn't work, i.e. not taking NULL
+ final int res = CGL.CGLSetPBuffer(contextHandle, 0, 0, 0, 0);
+ if (res != CGL.kCGLNoError) {
+ throw new GLException("Error code " + res + " while detaching context from pbuffer");
+ } */
+ return true;
}
- int err2 = CGL.CGLUnlockContext(ctx);
- if(DEBUG && CGL.kCGLNoError != err2) {
- System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this);
+
+ @Override
+ public boolean setSwapInterval(int interval) {
+ final IntBuffer lval = Buffers.newDirectIntBuffer(1);
+ lval.put(0, interval);
+ CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval);
+ return true;
}
- return CGL.kCGLNoError == err && CGL.kCGLNoError == err2;
- }
-
- public boolean setSwapInterval(int interval) {
- int[] lval = new int[] { interval } ;
- CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0);
- return true;
- }
- public boolean swapBuffers() {
- return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle);
- }
- }
+ @Override
+ public boolean swapBuffers() {
+ return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle);
+ }
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index 7b5efc31a..448e3e221 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.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,10 +42,10 @@ package jogamp.opengl.macosx.cgl;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
@@ -82,62 +82,75 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
// lifetime of a given GLPbuffer. This is not a fully general
// solution (for example, you can't share textures among a
// GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should
- // be enough to get things off the ground.
+ // 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){
this.id = id;
}
}
- private List<WeakReference<MacOSXCGLContext>> createdContexts = new ArrayList<WeakReference<MacOSXCGLContext>>();
-
+ /* pp */ List<WeakReference<MacOSXCGLContext>> createdContexts = new ArrayList<WeakReference<MacOSXCGLContext>>();
+
private boolean haveSetOpenGLMode = false;
private GLBackendType openGLMode = GLBackendType.NSOPENGL;
-
+
public MacOSXCGLDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
super(factory, comp, realized);
initOpenGLImpl(getOpenGLMode());
}
-
+
+ @Override
protected void setRealizedImpl() {
}
- protected long getNSViewHandle() {
- return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0;
- }
-
- protected void registerContext(MacOSXCGLContext ctx) {
+ @Override
+ protected void associateContext(GLContext ctx, 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) {
- createdContexts.add(new WeakReference<MacOSXCGLContext>(ctx));
+ if(bound) {
+ final MacOSXCGLContext osxCtx = (MacOSXCGLContext)ctx;
+ createdContexts.add(new WeakReference<MacOSXCGLContext>(osxCtx));
+ } else {
+ for(int i=0; i<createdContexts.size(); ) {
+ final MacOSXCGLContext _ctx = createdContexts.get(i).get();
+ if( _ctx == null || _ctx == ctx) {
+ createdContexts.remove(i);
+ } else {
+ i++;
+ }
+ }
+ }
}
}
- protected final void swapBuffersImpl() {
- // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- synchronized (createdContexts) {
- for (Iterator<WeakReference<MacOSXCGLContext>> iter = createdContexts.iterator(); iter.hasNext(); ) {
- WeakReference<MacOSXCGLContext> ref = iter.next();
- MacOSXCGLContext ctx = ref.get();
- if (ctx != null) {
- ctx.swapBuffers();
- } else {
- iter.remove();
- }
+
+ @Override
+ protected final void swapBuffersImpl(boolean doubleBuffered) {
+ if(doubleBuffered) {
+ synchronized (createdContexts) {
+ for(int i=0; i<createdContexts.size(); ) {
+ final MacOSXCGLContext ctx = createdContexts.get(i).get();
+ if (ctx != null) {
+ ctx.swapBuffers();
+ i++;
+ } else {
+ createdContexts.remove(i);
+ }
+ }
}
}
- }
-
- public GLDynamicLookupHelper getGLDynamicLookupHelper() {
- return getFactoryImpl().getGLDynamicLookupHelper(0);
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
+ @Override
+ public GLDynamicLookupHelper getGLDynamicLookupHelper() {
+ return getFactoryImpl().getGLDynamicLookupHelper(0);
}
// Support for "mode switching" as described in MacOSXCGLDrawable
@@ -148,17 +161,16 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
if (haveSetOpenGLMode) {
throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once");
}
-
- destroyImpl();
+ setRealized(false);
if (DEBUG) {
System.err.println("MacOSXCGLDrawable: Switching context mode " + openGLMode + " -> " + mode);
}
initOpenGLImpl(mode);
openGLMode = mode;
- haveSetOpenGLMode = true;
+ haveSetOpenGLMode = true;
}
public final GLBackendType getOpenGLMode() { return openGLMode; }
protected void initOpenGLImpl(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 71c0d5539..9ce71cfe9 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.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,17 +41,17 @@
package jogamp.opengl.macosx.cgl;
import java.nio.Buffer;
+import java.nio.FloatBuffer;
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;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
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;
@@ -60,21 +60,27 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.nativewindow.WrappedSurface;
+import jogamp.nativewindow.macosx.OSXDummyUpstreamSurfaceHook;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+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.util.ReflectionUtil;
-import com.jogamp.nativewindow.WrappedSurface;
+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;
-
+
public MacOSXCGLDrawableFactory() {
super();
@@ -90,31 +96,40 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
if(null!=tmp && tmp.isLibComplete()) {
macOSXCGLDynamicLookupHelper = tmp;
- /** FIXME ??
+ /** FIXME ??
CGL.getCGLProcAddressTable().reset(macOSXCGLDynamicLookupHelper);
*/
}
}
}
-
+
defaultDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
-
+
if(null!=macOSXCGLDynamicLookupHelper) {
// Register our GraphicsConfigurationFactory implementations
// The act of constructing them causes them to be registered
MacOSXCGLGraphicsConfigurationFactory.registerFactory();
if(GLProfile.isAWTAvailable()) {
try {
- ReflectionUtil.callStaticMethod("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory",
- "registerFactory", null, null, getClass().getClassLoader());
- } catch (JogampRuntimeException jre) { /* n/a .. */ }
+ ReflectionUtil.callStaticMethod("jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory",
+ "registerFactory", null, null, getClass().getClassLoader());
+ } catch (Exception jre) { /* n/a .. */ }
}
-
+
sharedMap = new HashMap<String, SharedResource>();
- }
+ }
+ }
+
+ @Override
+ protected final boolean isComplete() {
+ return null != macOSXCGLDynamicLookupHelper;
}
- protected final void destroy(ShutdownType shutdownType) {
+ @Override
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("MacOSXCGLDrawableFactory.shutdown");
+ }
if(null != sharedMap) {
sharedMap.clear();
sharedMap = null;
@@ -122,13 +137,13 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
defaultDevice = null;
/**
* Pulling away the native library may cause havoc ..
- *
- if(ShutdownType.COMPLETE == shutdownType && null != macOSXCGLDynamicLookupHelper) {
- macOSXCGLDynamicLookupHelper.destroy();
- macOSXCGLDynamicLookupHelper = null;
- } */
+ *
+ macOSXCGLDynamicLookupHelper.destroy();
+ */
+ macOSXCGLDynamicLookupHelper = null;
}
+ @Override
public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
return macOSXCGLDynamicLookupHelper;
}
@@ -136,37 +151,62 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
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,
+ SharedResource(MacOSXGraphicsDevice device, boolean valid,
boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels
- /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */) {
+ /* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */, 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
public final AbstractGraphicsDevice getDefaultDevice() {
return defaultDevice;
}
+ @Override
public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
if(null!=macOSXCGLDynamicLookupHelper && device instanceof MacOSXGraphicsDevice) {
return true;
@@ -174,7 +214,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- private HashSet<String> devicesTried = new HashSet<String>();
+ private final HashSet<String> devicesTried = new HashSet<String>();
private boolean getDeviceTried(String connection) {
synchronized (devicesTried) {
@@ -191,8 +231,9 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
devicesTried.remove(connection);
}
}
-
- /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) {
+
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) {
final String connection = adevice.getConnection();
SharedResource sr;
synchronized(sharedMap) {
@@ -201,7 +242,8 @@ 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;
@@ -209,96 +251,68 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
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 GLCapabilities caps = new GLCapabilities(glp);
- caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0);
- caps.setDepthBits(5);
- caps.setDoubleBuffered(false);
- caps.setOnscreen(false);
- caps.setPBuffer(true);
- final MacOSXCGLDrawable drawable = (MacOSXCGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) );
- if(null!=drawable) {
- drawable.setRealized(true);
- final GLContext context = drawable.createContext(null);
- if (null != context) {
- try {
- context.makeCurrent(); // could cause exception
- madeCurrent = context.isCurrent();
- if(madeCurrent) {
- GL gl = context.getGL();
- hasNPOTTextures = gl.isNPOTTextureAvailable();
- hasRECTTextures = gl.isExtensionAvailable("GL_EXT_texture_rectangle");
- hasAppleFloatPixels = gl.isExtensionAvailable("GL_APPLE_float_pixels");
- }
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
- gle.printStackTrace();
- }
- } finally {
- try {
- context.destroy();
- } catch (GLException gle) {
- if (DEBUG) {
- System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
- gle.printStackTrace();
- }
- }
+ }
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ final GLDrawableImpl sharedDrawable = createOnscreenDrawableImpl(createDummySurfaceImpl(sharedDevice, false, caps, caps, null, 64, 64));
+ sharedDrawable.setRealized(true);
+
+ 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
+ isValid = sharedContext.isCurrent();
+ if(isValid) {
+ 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) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: makeCurrent catched exception:");
+ gle.printStackTrace();
+ }
+ } finally {
+ try {
+ sharedContext.destroy();
+ } catch (GLException gle) {
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawableFactory.createShared: INFO: destroy catched exception:");
+ gle.printStackTrace();
}
}
- drawable.destroy();
}
+ 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;
}
-
+
+ @Override
protected final Thread getSharedResourceThread() {
return null;
}
-
- 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;
- }
-
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- // FIXME: not implemented .. needs a dummy OSX surface
- return null;
- }
-
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
- }
+ @Override
protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device);
}
+ @Override
protected GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -306,54 +320,81 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
return new MacOSXOnscreenCGLDrawable(this, target);
}
+ @Override
protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
- AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!caps.isPBuffer()) {
+ // Actual implementation is using PBuffer ...
+ final GLCapabilities modCaps = (GLCapabilities) caps.cloneMutable();
+ modCaps.setPBuffer(true);
+ modCaps.setBitmap(false);
+ config.setChosenCapabilities(modCaps);
return new MacOSXOffscreenCGLDrawable(this, target);
}
return new MacOSXPbufferCGLDrawable(this, target);
}
- public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- return true;
+ @Override
+ public boolean canCreateGLPbuffer(AbstractGraphicsDevice device, 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) {
+ final MacOSXGraphicsDevice device;
+ if( createNewDevice || !(deviceReq instanceof MacOSXGraphicsDevice) ) {
+ device = new MacOSXGraphicsDevice(deviceReq.getUnitID());
+ } else {
+ device = (MacOSXGraphicsDevice)deviceReq;
+ }
+ 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);
+ }
+ return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser,
+ new OSXDummyUpstreamSurfaceHook(width, height));
}
- protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true));
- ns.surfaceSizeChanged(width, height);
- return ns;
+ @Override
+ protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, 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);
+ return new WrappedSurface(config, windowHandle, upstream, true);
}
- protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WrappedSurface ns = new WrappedSurface(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true), windowHandle);
- return ns;
- }
-
+ @Override
protected GLContext createExternalGLContextImpl() {
return MacOSXExternalCGLContext.create(this);
}
+ @Override
public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
return false;
}
+ @Override
protected GLDrawable createExternalGLDrawableImpl() {
// FIXME
throw new GLException("Not yet implemented");
}
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("not supported in non AWT enviroment");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
@@ -362,21 +403,24 @@ 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() {
return GAMMA_RAMP_LENGTH;
}
+ @Override
protected boolean setGammaRamp(float[] ramp) {
- return CGL.setGammaRamp(ramp.length,
- ramp, 0,
- ramp, 0,
- ramp, 0);
+ final FloatBuffer rampNIO = Buffers.newDirectFloatBuffer(ramp);
+
+ return CGL.setGammaRamp(ramp.length, rampNIO, rampNIO, rampNIO);
}
+ @Override
protected Buffer getGammaRamp() {
return null;
}
+ @Override
protected void resetGammaRamp(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..cda8307c7 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
@@ -59,7 +59,7 @@ public class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLibraryBu
public final long toolGetProcAddress(long toolGetProcAddressHandle, 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 8393a688e..481c0b94b 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,40 +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 {
- long pixelformat;
- MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- long pixelformat) {
+ MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested) {
super(screen, capsChosen, capsRequested);
- this.pixelformat=pixelformat;
}
+ @Override
public Object clone() {
return super.clone();
}
- void setChosenPixelFormat(long pixelformat) {
- this.pixelformat=pixelformat;
- }
-
protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) {
- MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device);
+ 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,
@@ -91,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(AbstractGraphicsDevice device, IntBuffer attrToken, GLCapabilitiesImmutable caps, int ctp, int major, 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.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.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.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0;
+ ivalues.put(idx, caps.getNumSamples());
break;
default:
@@ -164,152 +155,158 @@ 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(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps, int ctp, int major, 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 GLCapabilitiesImmutable NSPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) {
+ static GLCapabilities NSPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) {
return PixelFormat2GLCapabilities(glp, pixelFormat, true);
}
- static long GLCapabilities2CGLPixelFormat(GLCapabilitiesImmutable caps, int ctp, int major, int minor) {
+ static long GLCapabilities2CGLPixelFormat(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps, int ctp, int major, 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);
- }
- if(caps.isPBuffer()) {
- attrs[i++] = CGL.kCGLPFAPBuffer;
- }
- if (caps.getPbufferFloatingPointBuffers()) {
- attrs[i++] = CGL.kCGLPFAColorFloat;
+ attrs.put(i++, CGL.kCGLPFAOpenGLProfile);
+ attrs.put(i++, MacOSXCGLContext.GLProfile2CGLOGLProfileValue(device, ctp, major, minor));
}
+ /**
+ if(!caps.isOnscreen() && caps.isPBuffer()) {
+ attrs.put(i++, CGL.kCGLPFAPBuffer);
+ if (caps.getPbufferFloatingPointBuffers()) {
+ 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);
+ IntBuffer numScreens = Buffers.newDirectIntBuffer(1);
+ 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 GLCapabilitiesImmutable CGLPixelFormat2GLCapabilities(long pixelFormat) {
+
+ static GLCapabilities CGLPixelFormat2GLCapabilities(long pixelFormat) {
return PixelFormat2GLCapabilities(null, pixelFormat, false);
}
- private static GLCapabilitiesImmutable PixelFormat2GLCapabilities(GLProfile glp, long pixelFormat, boolean nsUsage) {
- int len = cglInternalAttributeToken.length;
- int off = 0;
+ private static GLCapabilities PixelFormat2GLCapabilities(GLProfile glp, long pixelFormat, 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) {
glp = GLProfile.get(GLProfile.GL2);
}
- GLCapabilities caps = new GLCapabilities(glp);
+ 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);
@@ -317,16 +314,17 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.NSOpenGLPFAAlphaSize:
- caps.setAlphaBits(ivalues[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ 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);
@@ -335,21 +333,22 @@ 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:
break;
}
}
+ 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 1a9070aef..db2a1df68 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
@@ -34,13 +34,17 @@
package jogamp.opengl.macosx.cgl;
import jogamp.opengl.GLGraphicsConfigurationFactory;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLDrawableFactory;
/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits
@@ -50,21 +54,16 @@ import javax.media.opengl.GLCapabilitiesImmutable;
public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice.class, new MacOSXCGLGraphicsConfigurationFactory());
+ 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) {
- return chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, absScreen, false);
- }
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
- static MacOSXCGLGraphicsConfiguration chooseGraphicsConfigurationStatic(CapabilitiesImmutable capsChosen,
- CapabilitiesImmutable capsRequested,
- CapabilitiesChooser chooser,
- AbstractGraphicsScreen absScreen, boolean usePBuffer) {
if (absScreen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
@@ -77,11 +76,23 @@ public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurati
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - requested");
}
- if (chooser != null &&
- !(chooser instanceof GLCapabilitiesChooser)) {
+ if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
}
- return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, 0);
+ return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen, false);
+ }
+
+ static MacOSXCGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser,
+ AbstractGraphicsScreen absScreen, boolean usePBuffer) {
+ if (absScreen == null) {
+ throw new IllegalArgumentException("AbstractGraphicsScreen is null");
+ }
+ final AbstractGraphicsDevice device = absScreen.getDevice();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getDesktopFactory(), device);
+
+ return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index 58cea4ade..ebb0fc6d1 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.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.
*/
@@ -49,23 +49,21 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import com.jogamp.nativewindow.WrappedSurface;
-
-import jogamp.opengl.GLContextImpl;
+import jogamp.nativewindow.WrappedSurface;
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) {
super(drawable, null);
setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL );
- drawable.registerContext(this);
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
}
@@ -108,44 +106,30 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
}
AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX);
- MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps, pixelFormat);
+ MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps);
if(0 == currentDrawable) {
// set a fake marker stating a valid drawable
- currentDrawable = 1;
+ currentDrawable = 1;
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(currentDrawable);
+ WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, true);
return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle);
}
- protected boolean createImpl(GLContextImpl shareWith) throws GLException {
+ @Override
+ protected boolean createImpl(final long shareWithHandle) throws GLException {
return true;
}
- 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();
- }
-
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
+ @Override
protected void makeCurrentImpl() throws GLException {
}
+ @Override
protected void releaseImpl() throws GLException {
}
+ @Override
protected void destroyImpl() throws GLException {
}
@@ -155,14 +139,17 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
super(factory, comp, true);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
throw new GLException("Should not call this");
}
+ @Override
public int getWidth() {
throw new GLException("Should not call this");
}
+ @Override
public int getHeight() {
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 949963fa0..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
+++ /dev/null
@@ -1,64 +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.*;
-import jogamp.opengl.*;
-
-public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext
-{
- public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- 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;
- }
-
- public int getOffscreenContextReadBuffer() {
- return GL.GL_FRONT;
- }
-
- 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 f81cd725e..446a834b9 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.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.
*/
@@ -51,7 +51,8 @@ public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable {
super(factory, target);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new MacOSXOffscreenCGLContext(this, 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 9e051311c..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
+++ /dev/null
@@ -1,104 +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.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");
- }
- 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 80c54042f..c6f0c1383 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.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.
*/
@@ -45,15 +45,14 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable {
-
+
protected MacOSXOnscreenCGLDrawable(GLDrawableFactory factory, NativeSurface component) {
super(factory, component, false);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- final MacOSXOnscreenCGLContext ctx= new MacOSXOnscreenCGLContext(this, shareWith);
- registerContext(ctx);
- return ctx;
+ 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 7ba7d2d5a..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
+++ /dev/null
@@ -1,91 +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.GLException;
-import javax.media.opengl.GLPbuffer;
-
-import jogamp.opengl.GLContextImpl;
-
-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);
- }
-
- 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);
- }
-
- public void releasePbufferFromTexture() {
- }
-
- 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;
- }
-
- 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 1e49d1fc9..f6e8b8fa3 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.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,22 @@
* 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 java.lang.ref.WeakReference;
+
import javax.media.nativewindow.DefaultGraphicsConfiguration;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -54,7 +56,7 @@ import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.opengl.util.GLBuffers;
-public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
+public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
// Abstract interface for implementation of this drawable (either
// NSOpenGL-based or CGL-based)
interface GLBackendImpl {
@@ -64,24 +66,18 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
// Implementation object (either NSOpenGL-based or CGL-based)
protected GLBackendImpl impl;
-
+
// State for render-to-texture and render-to-texture-rectangle support
// private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
// private int texture; // actual texture object
- // Note that we can not store this in the NativeSurface because the
- // semantic is that contains an NSView
- protected long pBuffer;
protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight;
public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target) {
super(factory, target, false);
}
- protected void destroyImpl() {
- setRealized(false);
- }
-
+ @Override
protected void setRealizedImpl() {
if(realized) {
createPbuffer();
@@ -90,45 +86,45 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- final MacOSXPbufferCGLContext ctx = new MacOSXPbufferCGLContext(this, shareWith);
- registerContext(ctx);
- return ctx;
+ return new MacOSXCGLContext(this, shareWith);
}
- @Override
- protected long getNSViewHandle() {
- // pbuffer handle is NSOpenGLPixelBuffer
- return 0;
- }
-
- @Override
- public long getHandle() {
- return pBuffer;
- }
-
protected int getTextureTarget() { return pBufferTexTarget; }
protected int getTextureWidth() { return pBufferTexWidth; }
protected int getTextureHeight() { return pBufferTexHeight; }
-
+
protected void destroyPbuffer() {
- if (this.pBuffer != 0) {
- NativeSurface ns = getNativeSurface();
+ final MutableSurface ms = (MutableSurface) getNativeSurface();
+ final long pBuffer = ms.getSurfaceHandle();
+ if (0 != pBuffer) {
+ synchronized (createdContexts) {
+ for(int i=0; i<createdContexts.size(); ) {
+ final WeakReference<MacOSXCGLContext> ref = createdContexts.get(i);
+ final MacOSXCGLContext ctx = ref.get();
+ if (ctx != null) {
+ ctx.detachPBuffer();
+ i++;
+ } else {
+ createdContexts.remove(i);
+ }
+ }
+ }
impl.destroy(pBuffer);
- this.pBuffer = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ms.setSurfaceHandle(0);
}
}
private void createPbuffer() {
- final NativeSurface ns = getNativeSurface();
- final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration();
+ 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());
-
+ 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());
@@ -137,12 +133,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
}
- if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) {
- pBufferTexTarget = GL2.GL_TEXTURE_RECTANGLE;
- } else {
- pBufferTexTarget = GL.GL_TEXTURE_2D;
- }
- if ( GL2.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) {
+ pBufferTexTarget = GL.GL_TEXTURE_2D;
+ if ( null!=sr && sr.isNPOTTextureAvailable() ) {
pBufferTexWidth = getWidth();
pBufferTexHeight = getHeight();
} else {
@@ -150,19 +142,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
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)");
- }
- }
-
- pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
+ final int internalFormat = GL.GL_RGBA;
+ final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
if(DEBUG) {
System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+
", pbufferSize "+getWidth()+"x"+getHeight()+
@@ -175,14 +156,16 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
throw new GLException("pbuffer creation error: CGL.createPBuffer() failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(pBuffer);
+ ms.setSurfaceHandle(pBuffer);
}
+ @Override
public void setOpenGLMode(GLBackendType mode) {
super.setOpenGLMode(mode);
createPbuffer(); // recreate
}
+ @Override
protected void initOpenGLImpl(GLBackendType backend) {
switch (backend) {
case NSOPENGL:
@@ -194,14 +177,16 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
default:
throw new InternalError("Illegal implementation mode " + backend);
}
- }
-
+ }
+
// NSOpenGLPixelBuffer implementation
class NSOpenGLImpl implements GLBackendImpl {
+ @Override
public long create(int renderTarget, int internalFormat, int width, int height) {
return CGL.createPBuffer(renderTarget, internalFormat, width, height);
}
+ @Override
public void destroy(long pbuffer) {
CGL.destroyPBuffer(pbuffer);
}
@@ -209,6 +194,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
// CGL implementation
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);
@@ -218,12 +204,13 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
return pbuffer.get(0);
}
+ @Override
public void destroy(long pbuffer) {
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 a6fa01bad..21923531f 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
@@ -58,14 +58,15 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLGraphicsConfiguration;
public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new MacOSXAWTCGLGraphicsConfigurationFactory());
- }
+ 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) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -103,9 +104,9 @@ public class MacOSXAWTCGLGraphicsConfigurationFactory extends GLGraphicsConfigur
GraphicsConfiguration gc = device.getDefaultConfiguration();
MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capsChosen,
+ GraphicsConfigurationFactory.getFactory(macDevice, capsChosen).chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, macScreen);
+ chooser, macScreen, nativeVisualID);
if (macConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+macScreen);
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..eeaaa5872
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/openal/av/ALAudioSink.java
@@ -0,0 +1,947 @@
+/**
+ * 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.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.ALCcontext;
+import com.jogamp.openal.ALCdevice;
+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(int alBuffer) {
+ this.alBuffer = alBuffer;
+ }
+ public ALAudioFrame(int alBuffer, int pts, int duration, 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 = Debug.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(Throwable t) {
+ if( DEBUG ) {
+ System.err.println("ALAudioSink: Catched "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ alc = _alc;
+ al = _al;
+ alExt = _alExt;
+ staticAvailable = null != alc && null != al && null != alExt;
+ }
+
+ 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");
+ }
+
+ // Get the device specifier.
+ deviceSpecifier = alc.alcGetString(device, ALC.ALC_DEVICE_SPECIFIER);
+ if (deviceSpecifier == null) {
+ throw new RuntimeException(getThreadName()+": ALAudioSink: Error getting specifier for default OpenAL device");
+ }
+
+ // Create audio context.
+ 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) != ALC.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) ;
+ preferredAudioFormat = queryPreferredAudioFormat();
+ if( DEBUG ) {
+ System.out.println("ALAudioSink: OpenAL Extensions:"+al.alGetString(AL.AL_EXTENSIONS));
+ System.out.println("ALAudioSink: Null device OpenAL Extensions:"+alc.alcGetString(null, ALC.ALC_EXTENSIONS));
+ System.out.println("ALAudioSink: Device "+deviceSpecifier+" OpenAL Extensions:"+alc.alcGetString(device, ALC.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);
+ }
+
+ // Create source
+ {
+ alSource = new int[1];
+ al.alGenSources(1, alSource, 0);
+ final int err = al.alGetError();
+ if( AL.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 ( Exception e ) {
+ if( DEBUG ) {
+ System.err.println(e.getMessage());
+ }
+ destroy();
+ }
+ }
+ }
+
+ private final AudioFormat queryPreferredAudioFormat() {
+ int sampleRate = DefaultFormat.sampleRate;
+ final int[] value = new int[1];
+ alc.alcGetIntegerv(device, ALC.ALC_FREQUENCY, 1, value, 0);
+ if ( alc.alcGetError(device) == ALC.ALC_NO_ERROR ) {
+ sampleRate = value[0];
+ }
+ return new AudioFormat(sampleRate, DefaultFormat.sampleSize, DefaultFormat.channelCount, DefaultFormat.signed, DefaultFormat.fixedP, DefaultFormat.planar, DefaultFormat.littleEndian);
+ }
+
+ 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( ALC.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( ALC.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 (Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched "+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(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( AL.AL_NONE != alChannelLayout ) {
+ final int alSampleType = ALHelpers.getALSampleType(format.sampleSize, format.signed, format.fixedP);
+ if( AL.AL_NONE != alSampleType ) {
+ lockContext();
+ try {
+ final int alFormat = ALHelpers.getALFormat(alChannelLayout, alSampleType, hasSOFTBufferSamples, al, alExt);
+ return AL.AL_NONE != alFormat;
+ } finally {
+ unlockContext();
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean init(AudioFormat requestedFormat, float frameDuration, int initialQueueSize, int queueGrowAmount, int queueLimit) {
+ if( !staticAvailable ) {
+ return false;
+ }
+ alChannelLayout = ALHelpers.getDefaultALChannelLayout(requestedFormat.channelCount);
+ alSampleType = ALHelpers.getALSampleType(requestedFormat.sampleSize, requestedFormat.signed, requestedFormat.fixedP);
+ lockContext();
+ try {
+ if( AL.AL_NONE != alChannelLayout && AL.AL_NONE != alSampleType ) {
+ alFormat = ALHelpers.getALFormat(alChannelLayout, alSampleType, hasSOFTBufferSamples, al, alExt);
+ } else {
+ alFormat = AL.AL_NONE;
+ }
+ if( AL.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( AL.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;
+ }
+
+ private static int[] concat(int[] first, 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( AL.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 (Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched "+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 (Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched "+t.getClass().getName()+": "+t.getMessage());
+ t.printStackTrace();
+ }
+ }
+ alSource = null;
+ }
+
+ destroyBuffers();
+ } finally {
+ destroyContext();
+ }
+ if( null != device ) {
+ try {
+ alc.alcCloseDevice(device);
+ } catch (Throwable t) {
+ if( DEBUG ) {
+ System.err.println("Catched "+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 = AL.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], AL.AL_BUFFERS_PROCESSED, val, 0);
+ alErr = al.alGetError();
+ if( AL.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 "+(AL.AL_PLAYING == getSourceState(false))+", processed "+val[0]+", "+this);
+ }
+ unlockContext();
+ try {
+ Thread.sleep( sleep - 1 );
+ } catch (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( AL.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], AL.AL_BUFFER, 0); // explicit force zero buffer!
+ if(DEBUG_TRACE) {
+ al.alGetSourcei(alSource[0], AL.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(boolean wait, int inPTS, 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(AudioDataFrame audioDataFrame) {
+ return enqueueData(audioDataFrame.getPTS(), audioDataFrame.getData(), audioDataFrame.getByteSize());
+ }
+
+ @Override
+ public final AudioFrame enqueueData(int pts, ByteBuffer bytes, 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( AL.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while queueing buffer "+toHexString(alBufferNames[0])+". "+this);
+ }
+ alBufferBytesQueued += byteCount;
+ enqueuedFrameCount++;
+
+ 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 AL.AL_PLAYING == getSourceState(false);
+ } else {
+ return false;
+ }
+ }
+ private final int getSourceState(boolean ignoreError) {
+ final int[] val = new int[1];
+ al.alGetSourcei(alSource[0], AL.AL_SOURCE_STATE, val, 0);
+ final int alErr = al.alGetError();
+ if( AL.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 "+(AL.AL_PLAYING == getSourceState(false))+", "+this);
+ }
+ } finally {
+ unlockContext();
+ }
+ }
+ private final void playImpl() {
+ if( playRequested && AL.AL_PLAYING != getSourceState(false) ) {
+ al.alSourcePlay(alSource[0]);
+ final int alErr = al.alGetError();
+ if( AL.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 "+(AL.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( AL.AL_NO_ERROR != alErr ) {
+ throw new RuntimeException(getThreadName()+": ALError "+toHexString(alErr)+" while pausing. "+this);
+ }
+ }
+ }
+ private final void stopImpl(boolean ignoreError) {
+ if( AL.AL_STOPPED != getSourceState(ignoreError) ) {
+ playRequested = false;
+ al.alSourceStop(alSource[0]);
+ final int alErr = al.alGetError();
+ if( AL.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], AL.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], AL.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 "+(AL.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(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..2c1dfa237
--- /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(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..89e01edd8 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;
+ super(ad);
}
-
+
+ @Override
public final void setSubArrayVBOName(int vboName) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).getData().setVBOName(vboName);
- }
+ }
}
-
+
+ @Override
public final void addSubHandler(GLArrayHandlerFlat handler) {
subArrays.add(handler);
}
- private final void syncSubData(GL gl, boolean enable, boolean force, Object ext) {
+ private final void syncSubData(GL gl, 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(GL gl, boolean enable, 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..8a587980d 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;
+ super(ad);
}
+ @Override
public final void setSubArrayVBOName(int vboName) {
throw new UnsupportedOperationException();
}
-
+
+ @Override
public final void addSubHandler(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(GL gl, boolean enable, 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..7f7a99a2d 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 class GLFixedArrayHandler extends GLVBOArrayHandler {
public GLFixedArrayHandler(GLArrayDataEditable ad) {
- this.ad = ad;
+ super(ad);
}
-
+
+ @Override
public final void setSubArrayVBOName(int vboName) {
throw new UnsupportedOperationException();
}
-
+
+ @Override
public final void addSubHandler(GLArrayHandlerFlat handler) {
throw new UnsupportedOperationException();
}
-
- public final void syncData(GL gl, boolean enable, Object ext) {
+
+ @Override
+ public final void enableState(GL gl, boolean enable, 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..acec0510f 100644
--- a/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/GLFixedArrayHandlerFlat.java
@@ -35,7 +35,7 @@ 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 {
@@ -45,36 +45,37 @@ public class GLFixedArrayHandlerFlat implements GLArrayHandlerFlat {
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(GL gl, 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);
}
}
+ @Override
public final void enableState(GL gl, boolean enable, 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..5198cacfa
--- /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(GLArrayDataEditable ad) {
+ this.ad = ad;
+ }
+
+ @Override
+ public final boolean bindBuffer(GL gl, 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/EGLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/EGLMediaPlayerImpl.java
index 31f13297b..c39b78bb8 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,43 +44,40 @@ 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){
this.id = id;
}
- }
-
+ }
+
public static class EGLTextureFrame extends TextureSequence.TextureFrame {
-
+
public EGLTextureFrame(Buffer clientBuffer, Texture t, long khrImage, 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) {
super();
this.texType = texType;
@@ -88,36 +85,36 @@ public abstract class EGLMediaPlayerImpl extends GLMediaPlayerImpl {
}
@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(GL gl, int texName) {
+ final Texture texture = super.createTexImageImpl(gl, texName, width, height);
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);
// create EGLImage from texture
clientBuffer = null; // FIXME
nioTmp.put(0, EGL.EGL_NONE);
- image = eglExt.eglCreateImageKHR( eglDrawable.getDisplay(), eglCtx.getHandle(),
+ image = eglExt.eglCreateImageKHR( eglDrawable.getNativeSurface().getDisplayHandle(), eglCtx.getHandle(),
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];
+ 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.getDisplay(), 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(GL gl, 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.getDisplay(), eglTex.getImage());
+ eglExt.eglDestroyImageKHR(eglDrawable.getNativeSurface().getDisplayHandle(), eglTex.getImage());
}
if(0!=eglTex.getSync()) {
- eglExt.eglDestroySyncKHR(eglDrawable.getDisplay(), 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 d3d45e692..7cea51dc8 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,331 +28,670 @@
package jogamp.opengl.util.av;
import java.io.IOException;
-import java.net.URLConnection;
+import java.net.URI;
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.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.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);
protected static final String unknown = "unknown";
- protected State state;
+ protected volatile State state;
+ private final Object stateLock = new Object();
+
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. */
+
+ /** User requested URI stream location. */
+ protected 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 String cameraPath = null;
+ /** Optional camera properties, see {@link #cameraPath}. */
+ protected Map<String, String> cameraProps = null;
+
+ protected volatile float playSpeed = 1.0f;
+ protected float audioVolume = 1.0f;
+
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ protected int vid = GLMediaPlayer.STREAM_ID_AUTO;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ protected int aid = GLMediaPlayer.STREAM_ID_AUTO;
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected int width = 0;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected int height = 0;
- /** Video fps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Video avg. fps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected float fps = 0;
- /** Stream bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Video avg. frame duration in ms. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ protected float frame_duration = 0f;
+ /** Stream bps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected int bps_stream = 0;
- /** Video bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Video bps. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected int bps_video = 0;
- /** Audio bps. Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Audio bps. Shall be set by the {@link #initStreamImpl(int, 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. */
+ /** In frames. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ protected int videoFrames = 0;
+ /** In frames. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
+ protected int audioFrames = 0;
+ /** In ms. Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected int duration = 0;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Shall be set by the {@link #initStreamImpl(int, int)} method implementation. */
protected String acodec = unknown;
- /** Shall be set by the {@link #initGLStreamImpl(GL, int[])} method implementation. */
+ /** Shall be set by the {@link #initStreamImpl(int, 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>();
+
+ protected volatile int decodedFrameCount = 0;
+ protected int presentedFrameCount = 0;
+ protected int displayedFrameCount = 0;
+ protected 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;
+
+ /** 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;
+
+ protected TextureFrame[] videoFramesOrig = null;
+ protected Ringbuffer<TextureFrame> videoFramesFree = null;
+ protected Ringbuffer<TextureFrame> videoFramesDecoded = null;
+ protected volatile TextureFrame lastFrame = null;
+ /**
+ * @see #isGLOriented()
+ */
+ protected 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.textureType = GL.GL_UNSIGNED_BYTE;
+ this.textureInternalFormat = GL.GL_RGBA;
+ this.textureType = GL.GL_UNSIGNED_BYTE;
this.texUnit = 0;
this.state = State.Uninitialized;
}
@Override
- public void setTextureUnit(int u) { texUnit = u; }
-
+ public final void setTextureUnit(int u) { texUnit = u; }
+
@Override
- public int getTextureUnit() { return texUnit; }
-
- protected final void setTextureCount(int textureCount) {
- this.textureCount=textureCount;
- }
+ public final int getTextureUnit() { return texUnit; }
+
+ @Override
+ public final int getTextureTarget() { return textureTarget; }
+
@Override
public final int getTextureCount() { return textureCount; }
-
+
protected final void setTextureTarget(int target) { textureTarget=target; }
- protected final void setTextureFormat(int f) { textureFormat=f; }
+ protected final void setTextureFormat(int internalFormat, int format) {
+ textureInternalFormat=internalFormat;
+ textureFormat=format;
+ }
protected final void setTextureType(int t) { textureType=t; }
+ @Override
public final void setTextureMinMagFilter(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(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 GL2.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);
- }
+ 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 getDecodedFrameCount() { return decodedFrameCount; }
+
@Override
- public final synchronized void setPlaySpeed(float rate) {
- if(State.Uninitialized != state && setPlaySpeedImpl(rate)) {
- playSpeed = rate;
+ 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; }
+
+ @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(boolean flush) {
+ return pauseImpl(flush, 0);
+ }
+ private final State pauseImpl(boolean flush, int event_mask) {
+ synchronized( stateLock ) {
+ final State preState = state;
+ if( State.Playing == state ) {
+ event_mask = addStateEventMask(event_mask, GLMediaPlayer.State.Paused);
+ state = 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(GL gl) {
+ return destroyImpl(gl, 0);
+ }
+ private final State destroyImpl(GL gl, 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;
+ state = 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();
+ }
+ state = _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(float rate) {
+ if( null != audioSink ) {
+ audioSinkPlaySpeedSet = audioSink.setPlaySpeed(rate);
+ }
+ // 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;
+ }
+ /**
+ * 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;
}
- return state;
}
-
/**
- * 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#setVolume(float)} is not sufficient!
+ */
+ protected boolean setAudioVolumeImpl(float v) {
+ if( null != audioSink ) {
+ return audioSink.setVolume(v);
+ }
+ // still true, even if audioSink rejects command ..
+ return true;
+ }
+
+ @Override
+ public final void initStream(URI streamLoc, final int vid, final int aid, 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 String streamLocScheme = streamLoc.getScheme();
+ if( null != streamLocScheme && streamLocScheme.equals(CameraInputScheme) ) {
+ final String rawPath = streamLoc.getRawPath();
+ 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;
+ if ( this.streamLoc != null ) {
+ new Thread() {
+ public void run() {
+ try {
+ // StreamWorker may be used, see API-doc of StreamWorker
+ initStreamImpl(vid, aid);
+ } catch (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;
}
-
- 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.");
+
+ @Override
+ public final void initGL(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 (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(int desiredTextureCount) {
+ return desiredTextureCount < TEXTURE_COUNT_MIN ? TEXTURE_COUNT_MIN : desiredTextureCount;
+ }
+
+ protected TextureFrame[] createTexFrames(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 abstract TextureFrame createTexImage(GL gl, int texName);
+
+ protected final Texture createTexImageImpl(GL gl, int texName, int tWidth, 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));
}
}
@@ -361,9 +700,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
gl.glTexImage2D(
textureTarget, // target
0, // level
- GL.GL_RGBA, // internal format
- tWidth, // width
- tHeight, // height
+ textureInternalFormat, // internal format
+ tWidth, // width
+ tHeight, // height
0, // border
textureFormat,
textureType,
@@ -371,55 +710,691 @@ 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,
+
+ return com.jogamp.opengl.util.texture.TextureIO.newTexture(
+ texName, 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);
+ !isInGLOrientation);
+ }
+
+ protected void destroyTexFrame(GL gl, TextureFrame frame) {
+ frame.getTexture().destroy(gl);
+ }
+
+ @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(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");
+ }
+ }
+ }
+ }
+
+ protected TextureFrame cachedFrame = null;
+ protected long lastTimeMillis = 0;
+
+ private final boolean[] stGotVFrame = { false };
+
+ @Override
+ public final TextureFrame getNextTexture(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 (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ displayedFrameCount++;
+ return lastFrame;
+ }
+ }
+ protected void preNextTextureImpl(GL gl) {}
+ protected void postNextTextureImpl(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, 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(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(TextureFrame frame, long currentTimeMillis) {
+ decodedFrameCount++;
+ if( 0 == frame.getDuration() ) { // patch frame duration if not set already
+ frame.setDuration( (int) frame_duration );
+ }
+ synchronized(eventListenersLock) {
+ for(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 (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void makeCurrent(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 (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(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 ) {
+ try {
+ this.wait(); // wait until paused
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ public final synchronized void doResume() {
+ if( isRunning && !isActive ) {
+ shallPause = false;
+ if( Thread.currentThread() != this ) {
+ while( !isActive ) {
+ this.notifyAll(); // wake-up pause-block
+ try {
+ this.wait(); // wait until resumed
+ } catch (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 (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 (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 (InterruptedException e) {
+ isBlocked = false;
+ if( !shallStop && !shallPause ) {
+ streamErr = new StreamException("InterruptedException while decoding: "+GLMediaPlayerImpl.this.toString(), e);
+ }
+ } catch (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, 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(int event_mask) {
+ if( 0 != event_mask ) {
+ final long now = Platform.currentTimeMillis();
+ synchronized(eventListenersLock) {
+ for(Iterator<GLMediaEventListener> i = eventListeners.iterator(); i.hasNext(); ) {
+ i.next().attributesChanged(this, event_mask, now);
+ }
}
}
- 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) {
+ protected final void changeState(int event_mask, State newState) {
+ event_mask = addStateEventMask(event_mask, newState);
+ if( 0 != event_mask ) {
+ state = newState;
+ attributesUpdated( event_mask );
+ }
+ }
+
+ protected final void updateAttributes(int vid, int aid, int width, int height, int bps_stream,
+ int bps_video, int bps_audio, float fps,
+ int videoFrames, int audioFrames, int duration, String vcodec, String acodec) {
int event_mask = 0;
+ final boolean wasUninitialized = state == State.Uninitialized;
+
+ if( wasUninitialized ) {
+ event_mask |= GLMediaEventListener.EVENT_CHANGE_INIT;
+ state = 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;
@@ -427,12 +1402,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;
}
@@ -443,97 +1419,152 @@ 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(boolean isGLOriented) {
+ if( isInGLOrientation != isGLOriented ) {
+ if( DEBUG ) {
+ System.err.println("XXX gl-orient "+isInGLOrientation+" -> "+isGLOriented);
}
+ isInGLOrientation = isGLOriented;
+ 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;
+ public final URI getURI() {
+ return streamLoc;
}
- protected abstract void destroyImpl(GL gl);
@Override
- public final synchronized URLConnection getURLConnection() {
- return urlConn;
- }
+ public final int getVID() { return vid; }
+
+ @Override
+ public final int getAID() { return aid; }
@Override
- public final synchronized String getVideoCodec() {
+ public final String getVideoCodec() {
return vcodec;
}
@Override
- public final synchronized String getAudioCodec() {
+ public final String getAudioCodec() {
return acodec;
}
@Override
- public final synchronized long getTotalFrames() {
- return totalFrames;
+ public final int getVideoFrames() {
+ return videoFrames;
+ }
+
+ @Override
+ public final int getAudioFrames() {
+ return audioFrames;
}
@Override
- public final synchronized int getDuration() {
+ public final int getDuration() {
return duration;
}
-
+
@Override
- public final synchronized long getStreamBitrate() {
+ public final long getStreamBitrate() {
return bps_stream;
}
@Override
- public final synchronized int getVideoBitrate() {
+ public final int getVideoBitrate() {
return bps_video;
}
-
+
@Override
- public final synchronized int getAudioBitrate() {
+ public final int getAudioBitrate() {
return bps_audio;
}
-
+
@Override
- public final synchronized float getFramerate() {
+ public final float getFramerate() {
return fps;
}
@Override
- public final synchronized int getWidth() {
+ public final boolean isGLOriented() {
+ return isInGLOrientation;
+ }
+
+ @Override
+ public final int getWidth() {
return width;
}
@Override
- public final synchronized int getHeight() {
+ public final int getHeight() {
return height;
}
@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 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 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
@@ -557,13 +1588,30 @@ 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(String name) {
+ return attachedObjects.get(name);
+ }
+
+ @Override
+ public final Object attachObject(String name, Object obj) {
+ return attachedObjects.put(name, obj);
+ }
+
+ @Override
+ public final Object detachObject(String name) {
+ return attachedObjects.remove(name);
+ }
+
+ private final HashMap<String, Object> attachedObjects = new HashMap<String, Object>();
protected static final String toHexString(long v) {
return "0x"+Long.toHexString(v);
@@ -571,5 +1619,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
protected static final String toHexString(int v) {
return "0x"+Integer.toHexString(v);
}
-
-} \ No newline at end of file
+ protected static final int getPropIntVal(Map<String, String> props, String key) {
+ final String val = props.get(key);
+ try {
+ return Integer.valueOf(val).intValue();
+ } catch (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..6e006d9c0
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/JavaSoundAudioSink.java
@@ -0,0 +1,229 @@
+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 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 (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(float rate) {
+ return false; // FIXME
+ }
+
+ @Override
+ public final float getVolume() {
+ // FIXME
+ return volume;
+ }
+
+ @Override
+ public final boolean setVolume(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(AudioSink.AudioFormat format) {
+ return true;
+ }
+
+ @Override
+ public boolean init(AudioSink.AudioFormat requestedFormat, float frameDuration, int initialQueueSize, int queueGrowAmount, 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 (Exception e) {
+ initialized=false;
+ }
+ return true;
+ }
+
+ @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(AudioDataFrame audioDataFrame) {
+ int byteSize = audioDataFrame.getByteSize();
+ final ByteBuffer byteBuffer = audioDataFrame.getData();
+ final byte[] bytes = new byte[byteSize];
+ final int p = byteBuffer.position();
+ byteBuffer.get(bytes, 0, byteSize);
+ byteBuffer.position(p);
+
+ int written = 0;
+ int len;
+ while (byteSize > 0) {
+ len = auline.write(bytes, written, byteSize);
+ byteSize -= len;
+ written += len;
+ }
+ playImpl();
+ return audioDataFrame;
+ }
+
+ @Override
+ public AudioFrame enqueueData(int pts, ByteBuffer bytes, int byteCount) {
+ return enqueueData(new AudioDataFrame(pts, chosenFormat.getBytesDuration(byteCount), bytes, 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(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..8d3dbdf44
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/NullAudioSink.java
@@ -0,0 +1,129 @@
+package jogamp.opengl.util.av;
+
+
+import java.nio.ByteBuffer;
+
+import com.jogamp.opengl.util.av.AudioSink;
+
+public class NullAudioSink implements AudioSink {
+
+ @Override
+ public boolean isInitialized() {
+ return true;
+ }
+
+ private volatile float playSpeed = 1.0f;
+ private volatile boolean playRequested = false;
+ private float volume = 1.0f;
+
+ @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(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(AudioFormat format) {
+ return true;
+ }
+
+ @Override
+ public boolean init(AudioFormat requestedFormat, float frameDuration, int initialQueueSize, int queueGrowAmount, int queueLimit) {
+ return true;
+ }
+
+ @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() {
+ }
+
+ @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 0; }
+
+ @Override
+ public int getFreeFrameCount() {
+ return 1;
+ }
+
+ @Override
+ public AudioFrame enqueueData(AudioDataFrame audioDataFrame) {
+ return null;
+ }
+
+ @Override
+ public AudioFrame enqueueData(int pts, ByteBuffer bytes, int byteCount) {
+ 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 3d740d6b2..79129e563 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(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(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(GL gl, 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(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", NullGLMediaPlayer.class.getClassLoader());
+ URLConnection urlConn = IOUtil.getResource("jogl/util/data/av/test-ntsc01-57x32.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) {
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;
+ 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(int vid, 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(GL gl) throws IOException, GLException {
+ isInGLOrientation = true;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Returns {@link GLMediaPlayer#TEXTURE_COUNT_MIN}.
+ * </p>
+ */
+ @Override
+ protected int validateTextureCount(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(GL gl, int texName) {
+ final Texture texture = super.createTexImageImpl(gl, texName, width, height);
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(GL gl, TextureSequence.TextureFrame frame) {
+ super.destroyTexFrame(gl, frame);
}
-
+
private void validatePos() {
boolean considerPausing = false;
if( 0 > pos_ms) {
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 ce9df21cf..a6a6fba97 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,208 +41,377 @@ 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 */
+ boolean[] _loaded= new boolean[6];
+ /** util, format, codec, avresample, swresample */
+ VersionNumber[] _versions = new VersionNumber[5];
try {
- _ready = initSymbols();
+ _ready = initSymbols(_loaded, _versions);
} catch (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 {
+ if( avCodecVersion.getMajor() == 53 && avFormatVersion.getMajor() == 53 && avUtilVersion.getMajor() == 51 ) {
+ // lavc53.lavf53.lavu51
+ natives = new FFMPEGv08Natives();
+ } else if( avCodecVersion.getMajor() == 54 && avFormatVersion.getMajor() == 54 && avUtilVersion.getMajor() == 52 ) {
+ // lavc54.lavf54.lavu52.lavr01
+ natives = new FFMPEGv09Natives();
+ } else if( avCodecVersion.getMajor() == 55 && avFormatVersion.getMajor() == 55 && avUtilVersion.getMajor() == 52 ) {
+ // lavc55.lavf55.lavu52.lavr01
+ 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(boolean[] loaded, 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() {
+ public final List<List<String>> getToolLibNames() {
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("avutil-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-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("avformat-55"); // dummy future proof
- avformat.add("avformat-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-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("avcodec-55"); // dummy future proof
- avcodec.add("avcodec-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-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;
}
@@ -257,14 +426,12 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
@Override
- public boolean useToolGetProcAdressFirst(String funcName) {
+ public final boolean useToolGetProcAdressFirst(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 7d10cff4d..344ba48ee 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,797 @@
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.os.Platform;
+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.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.GLMediaPlayerImpl;
+import jogamp.opengl.util.av.impl.FFMPEGNatives.PixelFormat;
+import jogamp.opengl.util.av.impl.FFMPEGNatives.SampleFormat;
/***
* 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 PixelFormat#YUV420P}</li>
+ * <li>{@link PixelFormat#YUVJ420P}</li>
+ * <li>{@link PixelFormat#YUV422P}</li>
+ * <li>{@link PixelFormat#YUVJ422P}</li>
+ * <li>{@link PixelFormat#YUYV422}</li>
+ * <li>{@link PixelFormat#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>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: http://ffmpegmac.net/</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"));
+ }
+ libAVVersionGood = avCodecMajorVersionCC == avCodecVersion.getMajor() &&
+ avFormatMajorVersionCC == avFormatVersion.getMajor() &&
+ avUtilMajorVersionCC == avUtilVersion.getMajor() &&
+ ( !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 PixelFormat 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(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(int vid, 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.decodeURIIfFilePath(streamLoc);
+ 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(Platform.OS_TYPE) {
+ case ANDROID:
+ // ??
+ case FREEBSD:
+ case HPUX:
+ case LINUX:
+ case SUNOS:
+ resStreamLocS = dev_video_linux + cameraPath;
+ break;
+ case WINDOWS:
+ resStreamLocS = cameraPath;
+ 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 "+streamLoc+" -> "+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(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;
- switch(vBytesPerPixelPerPlane) {
- case 1: tf = GL2ES2.GL_RED; break;
- case 3: tf = GL2ES2.GL_RGB; break;
- case 4: tf = GL2ES2.GL_RGBA; break;
- default: throw new RuntimeException("Unsupported bytes-per-pixel / plane "+vBytesPerPixelPerPlane);
- }
- setTextureFormat(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 != vid ) {
+ 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 == aid ) {
+ 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 != vid ) {
+ int tf, tif=GL.GL_RGBA; // texture format and internal format
+ 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 = GL2ES2.GL_ALPHA; tif=GL2ES2.GL_ALPHA; singleTexComp = "a";
+ }
+ break;
+
+ case 2: if( vPixelFmt == PixelFormat.YUYV422 ) {
+ // YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr
+ // Stuffed into RGBA half width texture
+ tf = GL2ES2.GL_RGBA; tif=GL2ES2.GL_RGBA; break;
+ } else {
+ tf = GL2ES2.GL_RG; tif=GL2ES2.GL_RG; break;
+ }
+ case 3: tf = GL2ES2.GL_RGB; tif=GL.GL_RGB; break;
+ case 4: if( vPixelFmt == PixelFormat.BGRA ) {
+ tf = GL2ES2.GL_BGRA; tif=GL.GL_RGBA; break;
+ } else {
+ tf = GL2ES2.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(GL gl, 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 SampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ final boolean isAudioFormatSupported(int audioSampleFmt, int audioSampleRate, int audioChannels) {
+ final SampleFormat avFmt = SampleFormat.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 SampleFormat}.
+ * @param audioSampleRate sample rate in Hz (1/s)
+ * @param audioChannels number of channels
+ */
+ private final AudioFormat avAudioFormat2Local(SampleFormat audioSampleFmt, int audioSampleRate, 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(int vid, int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
+ int tWd0, int tWd1, int tWd2, int vW, int vH,
+ int aid, int audioSampleFmt, int audioSampleRate,
+ int audioChannels, 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 = PixelFormat.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 SampleFormat aSampleFmt;
+ avChosenAudioFormat = null;;
+ this.audioSamplesPerFrameAndChannel = 0;
+
+ if( STREAM_ID_NONE != aid ) {
+ aSampleFmt = SampleFormat.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(boolean isInGLOrientation, int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
+ int tWd0, int tWd1, int tWd2, int vW, 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 {
+ public final String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException {
if(State.Uninitialized == state) {
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 {
+ public final String getTextureLookupFragmentShaderImpl() throws IllegalStateException {
if(State.Uninitialized == state) {
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"+
+ 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"+
" vec2 u_off = vec2("+tc_w_1+", 0.0);\n"+
" 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).r;\n"+
- " u = texture2D(image, u_off+tc_half).r;\n"+
- " v = texture2D(image, v_off+tc_half).r;\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"+
+ " vec2 u_off = vec2("+tc_w_1+" , 0.0);\n"+
+ " 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(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(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(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(GL gl, 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, textureTarget, textureFormat, textureType);
+ }
+ 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(ByteBuffer sampleData, int data_size, int audio_pts) {
+ setFirstAudioPTS2SCR( audio_pts );
+ if( 1.0f == playSpeed || 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..b4b887bc9
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -0,0 +1,281 @@
+/**
+ * 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(long[] symbols, 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);
+
+ /** FFMPEG/libAV Audio Sample Format */
+ public static enum SampleFormat {
+ // 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 SampleFormat valueOf(int ordinal) throws IllegalArgumentException {
+ final SampleFormat[] all = SampleFormat.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)+"]");
+ }
+ };
+
+ /** FFMPEG/libAV Pixel Format */
+ public static enum PixelFormat {
+ // 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 PixelFormat valueOf(int ordinal) throws IllegalArgumentException {
+ final PixelFormat[] all = PixelFormat.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/FFMPEGStaticNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
new file mode 100644
index 000000000..22a045825
--- /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(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..05a94def8 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,51 +70,60 @@ 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(GL gl, 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(GL gl, TextureSequence.TextureFrame imgTex) {
+ super.destroyTexFrame(gl, imgTex);
}
-
+
@Override
protected void destroyImpl(GL gl) {
- _detachVideoRenderer(moviePtr);
if (moviePtr != 0) {
+ _stop(moviePtr);
+ _detachVideoRenderer(moviePtr);
_destroyInstance(moviePtr);
moviePtr = 0;
}
}
-
+
@Override
- protected void initGLStreamImpl(GL gl, int[] texNames) throws IOException {
+ protected void initStreamImpl(int vid, 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(!streamLoc.getScheme().equals("file")) {
+ throw new IOException("Only file schemes are allowed: "+streamLoc);
+ }
+ final String path=streamLoc.getPath();
+ if(DEBUG) {
+ System.out.println("initGLStream: clean path "+path);
+ }
+
+ if(DEBUG) {
+ System.out.println("initGLStream: p1 "+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);
+ if(DEBUG) {
+ System.out.println("initGLStream: p2 "+this);
+ }
}
-
@Override
- protected int getCurrentPositionImpl() {
+ protected final void initGLImpl(GL gl) throws IOException, GLException {
+ // NOP
+ isInGLOrientation = true;
+ }
+
+ @Override
+ protected int getAudioPTSImpl() {
return 0!=moviePtr ? _getCurrentPosition(moviePtr) : 0;
}
@@ -130,7 +137,7 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- public synchronized boolean startImpl() {
+ public synchronized boolean playImpl() {
if(0==moviePtr) {
return false;
}
@@ -150,16 +157,6 @@ 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) {
if(0==moviePtr) {
throw new GLException("OMX native instance null");
@@ -168,36 +165,33 @@ public class OMXGLMediaPlayer extends EGLMediaPlayerImpl {
}
@Override
- protected TextureSequence.TextureFrame getLastTextureImpl() {
- return lastTex;
- }
-
- @Override
- protected TextureSequence.TextureFrame getNextTextureImpl(GL gl, boolean blocking) {
+ protected int getNextTextureImpl(GL gl, 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;
+ 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) {
@@ -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..1f402f48b 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java
@@ -33,40 +33,47 @@ 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;
+ super(ad);
}
-
+
+ @Override
public final void setSubArrayVBOName(int vboName) {
throw new UnsupportedOperationException();
}
-
+
+ @Override
public final void addSubHandler(GLArrayHandlerFlat handler) {
throw new UnsupportedOperationException();
}
-
- public final void syncData(GL gl, boolean enable, Object ext) {
+
+ @Override
+ public final void enableState(GL gl, boolean enable, 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 void enableShaderState(GL2ES2 glsl, boolean enable, 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 +85,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,6 +95,7 @@ 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)
@@ -95,26 +104,69 @@ public class GLSLArrayHandler implements GLArrayHandler {
if(ad.getVBOName() != qi[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(GL2ES2 glsl, 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)
+ final int[] qi = new int[1];
+ glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0);
+ if(ad.getVBOName() != qi[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..34a381d7d 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java
@@ -37,7 +37,7 @@ 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 {
@@ -47,43 +47,57 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat {
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(GL gl, 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);
+ }
+ }*/
}
+ @Override
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);
+ 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..e153082e0 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;
+ super(ad);
}
-
+
+ @Override
public final void setSubArrayVBOName(int vboName) {
for(int i=0; i<subArrays.size(); i++) {
subArrays.get(i).getData().setVBOName(vboName);
- }
+ }
}
-
+
+ @Override
public final void addSubHandler(GLArrayHandlerFlat handler) {
subArrays.add(handler);
}
- private final void syncSubData(GL gl, boolean enable, boolean force, Object ext) {
+ private final void syncSubData(GL gl, 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(GL gl, boolean enable, 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..dba408554
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
@@ -0,0 +1,195 @@
+/**
+ * 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(int textureUnit, 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(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(PMVMatrix.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(PMVMatrix.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(GL2ES2 gl, int x, int y, int width, 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(GL2ES2 gl) {
+ if(null != pmvMatrixUniform) {
+ pmvMatrixUniform = null;
+ }
+ if(null != pmvMatrix) {
+ pmvMatrix.destroy();
+ pmvMatrix=null;
+ }
+ if(null != interleavedVBO) {
+ interleavedVBO.destroy(gl);
+ interleavedVBO=null;
+ }
+ if(null != sp) {
+ sp.destroy(gl);
+ sp=null;
+ }
+ }
+
+ public void display(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..458a9c94f 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncHook.java
@@ -29,87 +29,115 @@
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.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 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 (GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix) {
+ 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(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix,
+ Class<?> shaderRootClass, String shaderSrcRoot, String shaderBinRoot,
+ String vertexColorFile, String vertexColorLightFile,
+ String fragmentColorFile, String fragmentColorTextureFile) {
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(boolean v) { fixedFunction.setVerbose(v); }
public void destroy() {
fixedFunction.destroy(gl);
fixedFunction = null;
+ if(ownsPMVMatrix) {
+ pmvMatrix.destroy();
+ }
+ 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);
+ fixedFunction.glDrawArrays(gl, mode, first, count);
}
public void glDrawElements(int mode, int count, int type, java.nio.Buffer indices) {
- fixedFunction.validate(gl);
- gl.glDrawElements(mode, count, type, indices);
+ fixedFunction.glDrawElements(gl, mode, count, type, indices);
}
public void glDrawElements(int mode, int count, int type, long indices_buffer_offset) {
- fixedFunction.validate(gl);
- gl.glDrawElements(mode, count, type, indices_buffer_offset);
+ fixedFunction.glDrawElements(gl, mode, count, type, indices_buffer_offset);
}
public void glActiveTexture(int texture) {
- fixedFunction.glActiveTexture(gl, texture);
+ fixedFunction.glActiveTexture(texture);
gl.glActiveTexture(texture);
}
public void glEnable(int cap) {
- if(fixedFunction.glEnable(gl, cap, true)) {
+ if(fixedFunction.glEnable(cap, true)) {
gl.glEnable(cap);
}
}
public void glDisable(int cap) {
- if(fixedFunction.glEnable(gl, cap, false)) {
+ if(fixedFunction.glEnable(cap, false)) {
gl.glDisable(cap);
}
}
- public void glCullFace(int faceName) {
- fixedFunction.glCullFace(gl, faceName);
- gl.glCullFace(faceName);
- }
-
+ @Override
public void glGetFloatv(int pname, java.nio.FloatBuffer params) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetFloatv(pname, params);
@@ -117,6 +145,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
gl.glGetFloatv(pname, params);
}
+ @Override
public void glGetFloatv(int pname, float[] params, int params_offset) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetFloatv(pname, params, params_offset);
@@ -124,6 +153,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
gl.glGetFloatv(pname, params, params_offset);
}
+ @Override
public void glGetIntegerv(int pname, IntBuffer params) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetIntegerv(pname, params);
@@ -131,6 +161,7 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
gl.glGetIntegerv(pname, params);
}
+ @Override
public void glGetIntegerv(int pname, int[] params, int params_offset) {
if(PMVMatrix.isMatrixGetName(pname)) {
pmvMatrix.glGetIntegerv(pname, params, params_offset);
@@ -139,95 +170,193 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
gl.glGetIntegerv(pname, params, params_offset);
}
- //
+ public void glTexEnvi(int target, int pname, int value) {
+ fixedFunction.glTexEnvi(target, pname, value);
+ }
+ public void glGetTexEnviv(int target, int pname, IntBuffer params) {
+ fixedFunction.glGetTexEnviv(target, pname, params);
+ }
+ public void glGetTexEnviv(int target, int pname, int[] params, int params_offset) {
+ fixedFunction.glGetTexEnviv(target, pname, params, params_offset);
+ }
+ public void glBindTexture(int target, int texture) {
+ fixedFunction.glBindTexture(target, texture);
+ gl.glBindTexture(target, texture);
+ }
+ public void glTexImage2D(int target, int level, int internalformat, int width, int height, int border,
+ int format, int type, 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(int target, int level, int internalformat, int width, int height, int border,
+ int format, int type, 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(float size) {
+ fixedFunction.glPointSize(size);
+ }
+ public void glPointParameterf(int pname, float param) {
+ fixedFunction.glPointParameterf(pname, param);
+ }
+ public void glPointParameterfv(int pname, float[] params, int params_offset) {
+ fixedFunction.glPointParameterfv(pname, params, params_offset);
+ }
+ public void glPointParameterfv(int pname, java.nio.FloatBuffer params) {
+ fixedFunction.glPointParameterfv(pname, params);
+ }
+
+ //
// MatrixIf
//
public int glGetMatrixMode() {
return pmvMatrix.glGetMatrixMode();
}
+ @Override
public void glMatrixMode(int mode) {
pmvMatrix.glMatrixMode(mode);
}
+ @Override
public void glLoadMatrixf(java.nio.FloatBuffer m) {
pmvMatrix.glLoadMatrixf(m);
}
+ @Override
public void glLoadMatrixf(float[] m, int m_offset) {
glLoadMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset));
}
+ @Override
public void glPopMatrix() {
pmvMatrix.glPopMatrix();
}
+ @Override
public void glPushMatrix() {
pmvMatrix.glPushMatrix();
}
+ @Override
public void glLoadIdentity() {
pmvMatrix.glLoadIdentity();
}
+ @Override
public void glMultMatrixf(java.nio.FloatBuffer m) {
pmvMatrix.glMultMatrixf(m);
}
+ @Override
public void glMultMatrixf(float[] m, int m_offset) {
glMultMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset));
}
+ @Override
public void glTranslatef(float x, float y, float z) {
pmvMatrix.glTranslatef(x, y, z);
}
+ @Override
public void glRotatef(float angdeg, float x, float y, float z) {
pmvMatrix.glRotatef(angdeg, x, y, z);
}
+ @Override
public void glScalef(float x, float y, float z) {
pmvMatrix.glScalef(x, y, z);
}
+ public void glOrtho(double left, double right, double bottom, double top, double near_val, double far_val) {
+ glOrthof((float) left, (float) right, (float) bottom, (float) top, (float) near_val, (float) far_val);
+ }
+ @Override
public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) {
pmvMatrix.glOrthof(left, right, bottom, top, zNear, zFar);
}
+ public void glFrustum(double left, double right, double bottom, double top, double zNear, double zFar) {
+ glFrustumf((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar);
+ }
+ @Override
public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar) {
pmvMatrix.glFrustumf(left, right, bottom, top, zNear, zFar);
}
- //
+ //
// LightingIf
//
+ @Override
public void glColor4f(float red, float green, float blue, float alpha) {
- fixedFunction.glColor4fv(gl, GLBuffers.newDirectFloatBuffer(new float[] { red, green, blue, alpha }));
+ fixedFunction.glColor4f(gl, red, green, blue, alpha);
}
+ public void glColor4ub(byte red, byte green, byte blue, 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(int light, int pname, java.nio.FloatBuffer params) {
fixedFunction.glLightfv(gl, light, pname, params);
}
+ @Override
public void glLightfv(int light, int pname, float[] params, int params_offset) {
glLightfv(light, pname, GLBuffers.newDirectFloatBuffer(params, params_offset));
}
+ @Override
public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params) {
fixedFunction.glMaterialfv(gl, face, pname, params);
}
+ @Override
public void glMaterialfv(int face, int pname, float[] params, int params_offset) {
glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(params, params_offset));
}
+ @Override
public void glMaterialf(int face, int pname, float param) {
glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(new float[] { param }));
}
+
+ //
+ // Misc Simple States
+ //
+ @Override
public void glShadeModel(int mode) {
fixedFunction.glShadeModel(gl, mode);
}
+ public void glAlphaFunc(int func, float ref) {
+ fixedFunction.glAlphaFunc(func, ref);
+ }
+
+ /** ES2 supports CullFace implicit
+ public void glCullFace(int faceName) {
+ fixedFunction.glCullFace(faceName);
+ gl.glCullFace(faceName);
+ } */
//
// PointerIf
//
+ public void glClientActiveTexture(int textureUnit) {
+ fixedFunction.glClientActiveTexture(textureUnit);
+ }
+ @Override
public void glEnableClientState(int glArrayIndex) {
fixedFunction.glEnableClientState(gl, glArrayIndex);
}
+ @Override
public void glDisableClientState(int glArrayIndex) {
fixedFunction.glDisableClientState(gl, glArrayIndex);
}
+ @Override
public void glVertexPointer(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 +366,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
fixedFunction.glVertexPointer(gl, array);
}
+ @Override
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));
+ glVertexPointer(GLArrayDataWrapper.createFixed(GL_VERTEX_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
+ pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
+ @Override
public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ 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));
}
+ @Override
public void glColorPointer(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 +397,32 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glColorPointer(gl, array);
}
+ @Override
public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer) {
- glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, false, stride,
+ glColorPointer(GLArrayDataWrapper.createFixed(GL_COLOR_ARRAY, size, type, GLBuffers.isGLTypeFixedPoint(type), stride,
pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
+ @Override
public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ 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));
}
+ @Override
public void glNormalPointer(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 +431,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glNormalPointer(gl, array);
}
+ @Override
public void glNormalPointer(int type, int stride, java.nio.Buffer pointer) {
- glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, false, stride,
+ glNormalPointer(GLArrayDataWrapper.createFixed(GL_NORMAL_ARRAY, 3, type, GLBuffers.isGLTypeFixedPoint(type), stride,
pointer, 0, 0, 0, GL.GL_ARRAY_BUFFER));
}
+ @Override
public void glNormalPointer(int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ 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));
}
+ @Override
public void glTexCoordPointer(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 +462,29 @@ public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFun
}
fixedFunction.glTexCoordPointer(gl, array);
}
+ @Override
public void glTexCoordPointer(int size, int type, int stride, 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));
}
+ @Override
public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) {
- int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER);
+ 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();
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..42269588d 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,87 @@
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.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 = Debug.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(GL2ES2 gl, ShaderSelectionMode mode, 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(GL2ES2 gl, ShaderSelectionMode mode, PMVMatrix pmvMatrix,
+ Class<?> shaderRootClass, String shaderSrcRoot,
+ String shaderBinRoot,
+ String vertexColorFile, String vertexColorLightFile,
+ String fragmentColorFile, 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(ShaderSelectionMode mode) { requestedShaderSelectionMode=mode; }
+ public ShaderSelectionMode getCurrentShaderSelectionMode() { return currentShaderSelectionMode; }
+
public boolean verbose() { return verbose; }
- public void setVerbose(boolean v) { verbose=v; }
+ public void setVerbose(boolean v) { verbose = DEBUG || v; }
public boolean isValid() {
return shaderState.linked();
@@ -69,46 +123,83 @@ 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);
+ 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(GL2ES2 gl, float red, float green, float blue, 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");
}
}
+ //
+ // Arrays / States
+ //
+
+ public void glEnableClientState(GL2ES2 gl, int glArrayIndex) {
+ glToggleClientState(gl, glArrayIndex, true);
+ }
+
public void glDisableClientState(GL2ES2 gl, int glArrayIndex) {
- shaderState.useProgram(gl, true);
+ 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(GL2ES2 gl, int glArrayIndex, 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;
}
}
@@ -122,26 +213,235 @@ public class FixedFuncPipeline {
shaderState.vertexAttribPointer(gl, data);
}
- public void glColor4fv(GL2ES2 gl, FloatBuffer data ) {
+ public void glNormalPointer(GL2ES2 gl, 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(boolean enable, 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 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(GL2ES2 gl, 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 glBindTexture(int target, 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(int target, /* int level, */ int internalformat, /*, int width, int height, int border, */
+ 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(int target, int pname, 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 GL2ES1.GL_BLEND:
+ mode = 4;
+ break;
+ case GL2ES1.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(int value) {
+ if( value != textureEnvMode.get(activeTextureUnit) ) {
+ textureEnvMode.put(activeTextureUnit, value);
+ textureEnvModeDirty = true;
+ }
+ }
+ public void glGetTexEnviv(int target, int pname, IntBuffer params) { // FIXME
+ System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname));
+ }
+ public void glGetTexEnviv(int target, int pname, int[] params, int params_offset) { // FIXME
+ System.err.println("FixedFuncPipeline: Unimplemented glGetTexEnviv: target "+toHexString(target)+", pname "+toHexString(pname));
+ }
+
+ //
+ // Point Sprites
+ //
+ public void glPointSize(float size) {
+ pointParams.put(0, size);
+ pointParamsDirty = true;
+ }
+ public void glPointParameterf(int pname, 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 GL2ES2.GL_POINT_FADE_THRESHOLD_SIZE:
+ pointParams.put(4+3, param);
+ break;
+ }
+ pointParamsDirty = true;
+ }
+ public void glPointParameterfv(int pname, float[] params, 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(int pname, 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(GL2ES2 gl, GLRunnable2<Object,Object> glDrawAction, 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(GL gl, Object args) {
+ int[] _args = (int[])args;
+ gl.glDrawArrays(GL.GL_POINTS, _args[0], _args[1]);
+ return null;
+ }
+ };
+ private final void glDrawPointArrays(GL2ES2 gl, int first, int count) {
+ glDrawPoints(gl, glDrawArraysAction, new int[] { first, count });
+ }
+
+ //
+ // Lighting
+ //
+
public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) {
shaderState.useProgram(gl, true);
light -=GLLightingFunc.GL_LIGHT0;
@@ -179,17 +479,14 @@ 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);
}
}
@@ -201,10 +498,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 +509,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,17 +530,20 @@ 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) {
+
}
}
+ //
+ // Misc States
+ //
+
public void glShadeModel(GL2ES2 gl, int mode) {
shaderState.useProgram(gl, true);
GLUniformData ud = shaderState.getUniform(mgl_ShadeModel);
@@ -249,46 +553,135 @@ public class FixedFuncPipeline {
}
}
- 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(int func, 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(int cap, 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;
@@ -299,157 +692,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(GL2ES2 gl, int mode, int first, 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 GL2ES1.GL_POINTS:
+ glDrawPointArrays(gl, first, count);
+ return;
}
- if(0>cullFace) {
- faceName *= -1;
+ validate(gl, true);
+ if ( GL2.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(GL2ES2 gl, int mode, int count, int type, java.nio.Buffer indices) {
+ validate(gl, true);
+ if ( GL2.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, (int)(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, (int)(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, (int)(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( GL2ES1.GL_POINTS != mode ) {
+ ((GLES2)gl).glDrawElements(mode, count, type, indices);
+ } else {
+ // FIXME GL_POINTS !
+ ((GLES2)gl).glDrawElements(mode, count, type, indices);
+ }
+ }
+ }
+ public void glDrawElements(GL2ES2 gl, int mode, int count, int type, long indices_buffer_offset) {
+ validate(gl, true);
+ if ( GL2.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( GL2ES1.GL_POINTS != mode ) {
+ // FIXME GL_POINTS !
+ gl.glDrawElements(mode, count, type, indices_buffer_offset);
+ } else {
+ 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(GL2ES2 gl, 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) {
+ 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, 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(GL2ES2 gl, ShaderCode vp, ShaderCode fp, String maxTextureDefine) {
+ int rsVpPos = vp.defaultShaderCustomization(gl, true, true);
+ 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(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);
+ }
+ }
- shaderProgramColor = new ShaderProgram();
- shaderProgramColor.add(vertexColor);
- shaderProgramColor.add(fragmentColor);
- if(!shaderProgramColor.link(gl, System.err)) {
- throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor);
+ private final void loadShader(GL2ES2 gl, 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;
+
+ 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(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(GL2ES2 gl, ShaderSelectionMode mode, 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 +1115,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 +1143,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 +1152,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(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..45087ea2c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/jpeg/JPEGDecoder.java
@@ -0,0 +1,1517 @@
+/**
+ * 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) | data[9];
+ yDensity = (data[10] << 8) | data[11];
+ 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) | data[8] ) ;
+ flags1 = (short) ( (data[9] << 8) | data[10] ) ;
+ 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(String message) {
+ super(message);
+ }
+ }
+ @SuppressWarnings("serial")
+ public static class MarkerException extends CodecException {
+ final int marker;
+ MarkerException(int marker, 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(boolean progressive, int precision, int scanLines, int samplesPerLine, int componentsCount, 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(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(int compID, ComponentIn component) {
+ if( maxCompID < compID ) {
+ maxCompID = compID;
+ }
+ final int idx = compIDs.size();
+ checkBounds(idx);
+ compIDs.add(compID);
+ comps[idx] = component;
+ }
+ public final ComponentIn getCompByIndex(int i) {
+ checkBounds(i);
+ return comps[i];
+ }
+ public final ComponentIn getCompByID(int componentID) {
+ return getCompByIndex( compIDs.indexOf(componentID) );
+ }
+ public final int getCompID(int idx) {
+ return compIDs.get(idx);
+ }
+ public final boolean hasCompID(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 */
+ 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(int h, int v, int qttIdx) {
+ this.h = h;
+ this.v = v;
+ this.qttIdx = qttIdx;
+ }
+
+ public final void allocateBlocks(int blocksPerColumn, int blocksPerColumnForMcu, int blocksPerLine, 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(int row, 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 */
+ class ComponentOut {
+ private final ArrayList<byte[]> lines;
+ final float scaleX;
+ final float scaleY;
+
+ ComponentOut(ArrayList<byte[]> lines, float scaleX, 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(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(InputStream is) {
+ try {
+ bstream.setStream(is, false /* outputMode */);
+ } catch (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;
+ 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(byte[] data, int offset, 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(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++;
+ 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(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;
+ }
+ int mcusPerLine = (int) Math.ceil(frame.samplesPerLine / 8f / maxH);
+ 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;
+ }
+
+ private static class BinObjIdxed {
+ final BinObj children;
+ byte index;
+ BinObjIdxed() {
+ this.children = new BinObj();
+ this.index = 0;
+ }
+ }
+ private static class BinObj {
+ final boolean isValue;
+ final BinObj[] tree;
+ final byte b;
+
+ BinObj(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(int i) { return tree[i]; }
+ final void set(byte i, byte v) { tree[i] = new BinObj(v); }
+ final void set(byte i, BinObj v) { tree[i] = v; }
+ }
+
+ private BinObj buildHuffmanTable(int[] codeLengths, 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();
+ private static class Output {
+ private int blocksPerLine;
+ private int blocksPerColumn;
+ private int samplesPerLine;
+
+ private ArrayList<byte[]> buildComponentData(Frame frame, ComponentIn component) {
+ 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(int[] zz, byte[] dataOut, int[] dataIn, int[] qt) {
+ int v0, v1, v2, v3, v4, v5, v6, v7, t;
+ 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) {
+ 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) {
+ 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) {
+ int sample = 128 + ((p[i] + 8) >> 4);
+ dataOut[i] = (byte) ( sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample );
+ }
+ }
+ }
+
+ private static interface DecoderFunction {
+ void decode(ComponentIn component, int[] zz) throws IOException;
+ }
+
+ private 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(Frame frame, ArrayList<ComponentIn> components, int resetInterval,
+ int spectralStart, int spectralEnd, int successivePrev, 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 (MarkerException markerException) {
+ if(DEBUG) { System.err.println("JPEG.decodeScan: Marker exception: "+markerException.getMessage()); markerException.printStackTrace(); }
+ return markerException.getMarker();
+ } catch (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(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(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(ComponentIn component, 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(ComponentIn component, 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(ComponentIn component, int[] zz) throws IOException {
+ zz[0] |= readBit() << successive;
+ }
+ }
+
+ class ACFirstDecoder implements DecoderFunction {
+ @Override
+ public void decode(ComponentIn component, int[] zz) throws IOException {
+ if (eobrun > 0) {
+ eobrun--;
+ return;
+ }
+ int k = spectralStart, 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(ComponentIn component, int[] zz) throws IOException {
+ int k = spectralStart, e = spectralEnd, 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(ComponentIn component, DecoderFunction decoder, int mcu, int row, 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(ComponentIn component, DecoderFunction decoder, 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(JPEGDecoder.ColorSink pixelStorage, int width, 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(float a) {
+ return (byte) ( a < 0f ? 0 : a > 255f ? 255 : a );
+ }
+
+ private static String toHexString(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..5e177b8c3 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) {
this.val = val;
}
- public static FilterType getByVal(int i) {
+ private static HashMap<Integer, FilterType> byVal;
+
+ static {
+ byVal = new HashMap<Integer, FilterType>();
for (FilterType ft : values()) {
- if (ft.val == i)
- return ft;
+ byVal.put(ft.val, 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);
- }
-
- 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;
- }
-
- 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(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..79eed8f85 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;
@@ -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..ac7b858e1 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,10 +78,16 @@ 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)
@@ -89,13 +98,14 @@ public class ImageInfo {
/**
* 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
@@ -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,16 +167,11 @@ 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;
}
@@ -183,12 +188,6 @@ public class ImageInfo {
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..e6afd8694 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(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(ImageInfo imgInfo, SampleType stype, boolean unpackedMode) {
+ this(imgInfo, stype, unpackedMode, null, null);
+ }
+
+ /**
+ * If a preallocated array is passed, the copy is shallow
+ */
+ ImageLine(ImageInfo imgInfo, SampleType stype, boolean unpackedMode, int[] sci, 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 */
+ /** Sets row number (0 : Rows-1) */
public void setRown(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() {
+ 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() {
+ 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(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(ImageLine line) {
+ System.out.println(line);
+ 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..4636c3955
--- /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, PngChunkPLTE pal, PngChunkTRNS trns, int[] buf) {
+ boolean isalpha = trns != null;
+ int channels = isalpha ? 4 : 3;
+ int nsamples = line.imgInfo.cols * channels;
+ if (buf == null || buf.length < nsamples)
+ buf = new int[nsamples];
+ if (!line.samplesUnpacked)
+ line = line.unpackToNewImageLine();
+ boolean isbyte = line.sampleType == SampleType.BYTE;
+ int nindexesWithAlpha = trns != null ? trns.getPalletteAlpha().length : 0;
+ for (int c = 0; c < line.imgInfo.cols; c++) {
+ int index = isbyte ? (line.scanlineb[c] & 0xFF) : line.scanline[c];
+ pal.getEntryRgb(index, buf, c * channels);
+ if (isalpha) {
+ int alpha = index < nindexesWithAlpha ? trns.getPalletteAlpha()[index] : 255;
+ buf[c * channels + 3] = alpha;
+ }
+ }
+ return buf;
+ }
+
+ public static int[] palette2rgb(ImageLine line, PngChunkPLTE pal, 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(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(ImageLine line) {
+ 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(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(ImageLine line, int column) {
+ int offset = column * line.channels;
+ return (line.scanline[offset] << 16) + (line.scanline[offset + 1] << 8) + (line.scanline[offset + 2]);
+ }
+
+ public static int getPixelARGB8(ImageLine line, int column) {
+ 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(ImageLine line, 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(ImageLine line, int col, int r, int g, int b) {
+ col *= line.channels;
+ line.scanline[col++] = r;
+ line.scanline[col++] = g;
+ line.scanline[col] = b;
+ }
+
+ public static void setPixelRGB8(ImageLine line, int col, int rgb) {
+ setPixelRGB8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
+ }
+
+ public static void setPixelsRGBA8(ImageLine line, 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(ImageLine line, int col, int r, int g, int b, 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(ImageLine line, int col, int rgb) {
+ setPixelRGBA8(line, col, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF, (rgb >> 24) & 0xFF);
+ }
+
+ public static void setValD(ImageLine line, int i, double d) {
+ line.scanline[i] = double2int(line, d);
+ }
+
+ public static int interpol(int a, int b, int c, int d, double dx, double dy) {
+ // a b -> x (0-1)
+ // c d
+ //
+ double e = a * (1.0 - dx) + b * dx;
+ double f = c * (1.0 - dx) + d * dx;
+ return (int) (e * (1 - dy) + f * dy + 0.5);
+ }
+
+ public static double int2double(ImageLine line, int p) {
+ return line.bitDepth == 16 ? p / 65535.0 : p / 255.0;
+ // TODO: replace my multiplication? check for other bitdepths
+ }
+
+ public static double int2doubleClamped(ImageLine line, int p) {
+ // TODO: replace my multiplication?
+ 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(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(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(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);
+ }
+
+ /**
+ * 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(ImageInfo imgInfo, int[] src, int[] dst, boolean scale) {
+ int len1 = imgInfo.samplesPerRow;
+ 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(ImageInfo imgInfo, byte[] src, byte[] dst, boolean scale) {
+ int len1 = imgInfo.samplesPerRow;
+ 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(ImageInfo imgInfo, int[] src, int[] dst, boolean scale) {
+ 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(ImageInfo imgInfo, byte[] src, byte[] dst, boolean scale) {
+ 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(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(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..fb2cf5910
--- /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(ImageInfo imgInfo, SampleType stype, boolean unpackedMode, int rowOffset, int nRows, 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(int imrow) {
+ 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;
+ 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(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(int mrow) {
+ if (mrow < 0 || mrow > nRows)
+ throw new PngjException("Bad row " + mrow + ". Should be positive and less than " + nRows);
+ 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..e099c4f6a
--- /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(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(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(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(int[] src, int[] dst, 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(int[] src, 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(byte[] src, byte[] dst, 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(byte[] src, 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(int[][] imageInt) {
+ this.imageInt = imageInt;
+ }
+
+ short[][] getImageShort() {
+ return imageShort;
+ }
+
+ void setImageShort(short[][] imageShort) {
+ this.imageShort = imageShort;
+ }
+
+ byte[][] getImageByte() {
+ return imageByte;
+ }
+
+ void setImageByte(byte[][] imageByte) {
+ this.imageByte = imageByte;
+ }
+
+ static void test() {
+ Random rand = new Random();
+ 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);
+ 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(String[] args) {
+ test();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
index 1016b1b64..9e64c3eb1 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngHelper.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngHelperInternal.java
@@ -4,37 +4,52 @@ 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.
+ * Some utility static methods for internal use.
* <p>
- * See also <code>FileHelper</code> (if not sandboxed).
+ * Client code should not normally use this class
* <p>
- * Client code should rarely need these methods.
*/
-public class PngHelper {
+public class PngHelperInternal {
/**
* 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
+ /**
+ * UTF-8 is only used for some chunks
+ */
+ public static Charset charsetUTF8 = Charset.forName("UTF-8");
static 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(double d) {
+ return (int) (d * 100000.0 + 0.5);
+ }
+
+ public static double intToDouble100000(int i) {
+ return i / 100000.0;
+ }
+
public static int readByte(InputStream is) {
try {
return is.read();
} catch (IOException e) {
- throw new PngjOutputException(e);
+ throw new PngjInputException("error reading byte", e);
}
}
/**
* -1 if eof
- *
+ *
* PNG uses "network byte order"
*/
public static int readInt2(InputStream is) {
@@ -111,7 +126,7 @@ public class PngHelper {
}
/**
- * guaranteed to read exactly len bytes. throws error if it cant
+ * guaranteed to read exactly len bytes. throws error if it can't
*/
public static void readBytes(InputStream is, byte[] b, int offset, int len) {
if (len == 0)
@@ -121,7 +136,7 @@ public class PngHelper {
while (read < len) {
int n = is.read(b, offset + read, len - read);
if (n < 1)
- throw new RuntimeException("error reading bytes, " + n + " !=" + len);
+ throw new PngjInputException("error reading bytes, " + n + " !=" + len);
read += n;
}
} catch (IOException e) {
@@ -129,6 +144,26 @@ public class PngHelper {
}
}
+ public static void skipBytes(InputStream is, long len) {
+ try {
+ while (len > 0) {
+ 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 (IOException e) {
+ throw new PngjInputException(e);
+ }
+ }
+
public static void writeBytes(OutputStream os, byte[] b) {
try {
os.write(b);
@@ -150,26 +185,8 @@ public class PngHelper {
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>() {
+ @Override
protected CRC32 initialValue() {
return new CRC32();
}
@@ -180,34 +197,74 @@ public class PngHelper {
return crcProvider.get();
}
- static final byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 }; // png magic
+ // / filters
+ public static int filterRowNone(int r) {
+ return (int) (r & 0xFF);
+ }
- public static double resMetersToDpi(long res) {
- return (double) res * 0.0254;
+ public static int filterRowSub(int r, int left) {
+ return ((int) (r - left) & 0xFF);
}
- public static long resDpiToMeters(double dpi) {
- return (long) (dpi / 0.0254 + 0.5);
+ public static int filterRowUp(int r, int up) {
+ return ((int) (r - up) & 0xFF);
}
- public static int doubleToInt100000(double d) {
- return (int) (d * 100000.0 + 0.5);
+ public static int filterRowAverage(int r, int left, int up) {
+ return (r - (left + up) / 2) & 0xFF;
}
- public static double intToDouble100000(int i) {
- return i / 100000.0;
+ public static int filterRowPaeth(int r, int left, int up, int upleft) { // a = left, b = above, c = upper left
+ return (r - filterPaethPredictor(left, up, upleft)) & 0xFF;
}
- public static int clampTo_0_255(int i) {
- return i > 255 ? 255 : (i < 0 ? 0 : i);
+ public static int unfilterRowNone(int r) {
+ return (int) (r & 0xFF);
}
- public static int clampTo_0_65535(int i) {
- return i > 65535 ? 65535 : (i < 0 ? 0 : i);
+ public static int unfilterRowSub(int r, int left) {
+ return ((int) (r + left) & 0xFF);
+ }
+
+ 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;
+ }
+
+ public static int unfilterRowPaeth(int r, int left, int up, 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(PngReader pngr) {
+ pngr.initCrctest();
}
- public static int clampTo_128_127(int x) {
- return x > 127 ? 127 : (x < -128 ? -128 : x);
+ public final static long getCrctestVal(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..cdad09809 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 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(int len, 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(InputStream iStream, int lenFirstChunk, 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); //
+ 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) {
+ 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);
+ 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 {
+ if (ended)
+ return -1; // can happen only when raw reading, see Pngreader.readAndSkipsAllRows()
if (toReadThisChunk == 0)
- throw new RuntimeException("this should not happen");
+ throw new PngjExceptionInternal("this should not happen");
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;
}
@@ -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..411d18819 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngIDatChunkOutputStream.java
@@ -7,23 +7,23 @@ 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);
+ this(outputStream, 0);
}
PngIDatChunkOutputStream(OutputStream outputStream, int size) {
- super(size);
+ super(size > 0 ? size : SIZE_DEFAULT);
this.outputStream = outputStream;
}
@Override
- public final void flushBuffer(byte[] b, int len) {
+ protected final void flushBuffer(byte[] b, int len) {
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..0412beb8c 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(InputStream inputStream, String filenameOrDescription) {
+ this.filename = filenameOrDescription == null ? "" : filenameOrDescription;
+ this.inputStream = inputStream;
+ this.chunksList = new ChunksList(null);
+ this.metadata = new PngMetadata(chunksList);
+ // starts reading: signature
+ 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;
+ int clen = PngHelperInternal.readInt4(inputStream);
+ offset += 4;
+ if (clen != 13)
+ throw new PngjInputException("IDHR chunk len != 13 ?? " + clen);
+ 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;
+ PngChunkIHDR ihdr = (PngChunkIHDR) readChunk(chunkid, clen, false);
+ boolean alpha = (ihdr.getColormodel() & 0x04) != 0;
+ boolean palette = (ihdr.getColormodel() & 0x01) != 0;
+ 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 (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 (Exception e) {
+ }
+ currentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
+ }
+ if (shouldCloseStream) {
+ try {
+ inputStream.close();
+ } catch (Exception e) {
+ throw new PngjInputException("error closing input stream!", e);
+ }
+ }
+ }
+
+ // nbytes: NOT including the filter byte. leaves result in rowb
+ private void unfilterRow(int nbytes) {
+ 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(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] = (byte) (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] = (byte) (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;
+ 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;
+ }
+ 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();
+ 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(byte[] chunkid, int clen, 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));
+ String chunkidstr = ChunkHelper.toString(chunkid);
+ 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 {
+ 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(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(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(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(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(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(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(int nrow) {
+ return readRow(nrow);
+ }
+
+ private void decodeLastReadRowToInt(int[] buffer, 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(byte[] buffer, 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(int rowOffset, int nRows, 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");
+ ImageLines imlines = new ImageLines(imgInfo, SampleType.INT, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ int bytesread = readRowRaw(j); // read and perhaps discards
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToInt(imlines.scanlines[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ 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++) {
+ int bytesread = readRowRaw(i);
+ int j = deinterlacer.getCurrRowReal();
+ 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(int rowOffset, int nRows, 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");
+ ImageLines imlines = new ImageLines(imgInfo, SampleType.BYTE, unpackedMode, rowOffset, nRows, rowStep);
+ if (!interlaced) {
+ for (int j = 0; j < imgInfo.rows; j++) {
+ int bytesread = readRowRaw(j); // read and perhaps discards
+ int mrow = imlines.imageRowToMatrixRowStrict(j);
+ if (mrow >= 0)
+ decodeLastReadRowToByte(imlines.scanlinesb[mrow], bytesread);
+ }
+ } else { // and now, for something completely different (interlaced)
+ 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++) {
+ int bytesread = readRowRaw(i);
+ int j = deinterlacer.getCurrRowReal();
+ 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
+ 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 (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(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(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(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(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(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(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(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..2f475aab1 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 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
+
+ // 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(OutputStream outputStream, 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
@@ -67,171 +101,156 @@ public class PngWriter {
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);
+ Deflater def = new Deflater(compLevel);
+ def.setStrategy(deflaterStrategy);
+ datStreamDeflated = new DeflaterOutputStream(datStream, def);
+ writeSignatureAndIHDR();
+ writeFirstChunks();
+ }
+
+ 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]++;
}
- 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() {
+ 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();
+ 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
+ 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(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 (byte x : row) { // optimized
+ rowb[j++] = x;
+ }
+ } else { // 16 bitspc
+ for (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(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 (int x : row) { // optimized
+ rowb[j++] = (byte) x;
+ }
+ } else { // 16 bitspc
+ for (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) {
@@ -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(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
+ 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(int rown) {
+ filterRow(rown);
+ try {
+ datStreamDeflated.write(rowbfilter, 0, imgInfo.bytesPerRow + 1);
+ } catch (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] = (byte) 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] = (byte) 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 -= (int) rowbfilter[i];
+ else
+ s += (int) 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)
- */
- 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
+ * TODO: this should be more customizable
*/
private void copyChunks(PngReader reader, int copy_mask, boolean onlyAfterIdat) {
- boolean idatDone = currentChunkGroup >= ChunkList.CHUNK_GROUP_4_IDAT;
+ 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 (PngChunk chunk : reader.getChunksList().getChunks()) {
int group = chunk.getChunkGroup();
- if (group < ChunkList.CHUNK_GROUP_4_IDAT && idatDone)
+ if (group < ChunksList.CHUNK_GROUP_4_IDAT && idatDone)
continue;
boolean copy = false;
if (chunk.crit) {
@@ -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,13 +419,15 @@ 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) {
copyChunks(reader, copy_mask, false);
@@ -438,25 +436,254 @@ public class PngWriter {
/**
* 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) {
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()");
+ double compressed = (double) datStream.getCountFlushed();
+ 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 (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(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(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(int idatMaxSize) {
+ this.idatMaxSize = idatMaxSize;
+ }
+
+ /**
+ * if true, input stream will be closed after ending write
+ * <p>
+ * default=true
+ */
+ public void setShouldCloseStream(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(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(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(ImageLine imgline, 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(int[] newrow) {
+ writeRow(newrow, -1);
+ }
+
+ /**
+ * Alias to writeRowInt
+ *
+ * @see #writeRowInt(int[], int)
+ */
+ public void writeRow(int[] newrow, 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(int[] newrow, 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(byte[] newrow, int rown) {
+ prepareEncodeRow(rown);
+ encodeRowFromByte(newrow);
+ filterAndSend(rown);
+ }
+
+ /**
+ * Writes all the pixels, calling writeRowInt() for each image row
+ */
+ public void writeRowsInt(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(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(boolean useUnpackedMode) {
+ this.unpackedMode = useUnpackedMode;
+ }
+
}
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java b/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
index 4a45cb5bf..97e24fc73 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/PngjException.java
@@ -2,9 +2,9 @@ package jogamp.opengl.util.pngj;
/**
* Generic exception
- *
+ *
* @author Hernan J Gonzalez
- *
+ *
*/
public class PngjException extends RuntimeException {
private static final long serialVersionUID = 1L;
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..5da70de7b
--- /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(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PngjExceptionInternal(String message) {
+ super(message);
+ }
+
+ public PngjExceptionInternal(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..f68458d19 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;
diff --git a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
index bbec247fb..4516a0886 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/ProgressiveOutputStream.java
@@ -4,10 +4,12 @@ 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) {
this.size = size;
@@ -49,8 +51,8 @@ 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) {
while (forced || count >= size) {
@@ -60,6 +62,7 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
if (nb == 0)
return;
flushBuffer(buf, nb);
+ countFlushed += nb;
int bytesleft = count - nb;
count = bytesleft;
if (bytesleft > 0)
@@ -67,5 +70,9 @@ abstract class ProgressiveOutputStream extends ByteArrayOutputStream {
}
}
- 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..4e8bf5635 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(String x) {
+ return x.getBytes(PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(byte[] x) {
+ return new String(x, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to String using Latin1 (ISO-8859-1)
+ */
+ public static String toString(byte[] x, int offset, int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetLatin1);
+ }
+
+ /**
+ * Converts to bytes using UTF-8
+ */
+ public static byte[] toBytesUTF8(String x) {
+ return x.getBytes(PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(byte[] x) {
+ return new String(x, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * Converts to string using UTF-8
+ */
+ public static String toStringUTF8(byte[] x, int offset, int len) {
+ return new String(x, offset, len, PngHelperInternal.charsetUTF8);
+ }
+
+ /**
+ * critical chunk : first letter is uppercase
+ */
+ public static boolean isCritical(String id) {
+ return (Character.isUpperCase(id.charAt(0)));
+ }
+
+ /**
+ * public chunk: second letter is uppercase
+ */
+ public static boolean isPublic(String id) { //
+ return (Character.isUpperCase(id.charAt(1)));
+ }
+
+ /**
+ * Safe to copy chunk: fourth letter is lower case
+ */
+ public static boolean isSafeToCopy(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(PngChunk c) {
+ return c instanceof PngChunkUNKNOWN;
+ }
+
+ /**
+ * Finds position of null byte in array
+ *
+ * @param b
+ * @return -1 if not found
+ */
+ public static int posNullByte(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(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, getInflater());
+ 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 {
+ synchronized (tmpbuffer) {
+ int len;
+ while ((len = in.read(tmpbuffer)) > 0) {
+ out.write(tmpbuffer, 0, len);
+ }
+ }
+ }
+
+ public static boolean maskMatch(int v, int mask) {
+ return (v & mask) != 0;
+ }
+
+ /**
+ * Returns only the chunks that "match" the predicate
+ *
+ * See also trimList()
+ */
+ public static List<PngChunk> filterList(List<PngChunk> target, ChunkPredicate predicateKeep) {
+ List<PngChunk> result = new ArrayList<PngChunk>();
+ for (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(List<PngChunk> target, ChunkPredicate predicateRemove) {
+ Iterator<PngChunk> it = target.iterator();
+ int cont = 0;
+ while (it.hasNext()) {
+ 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(PngChunk c1, 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(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() {
+ 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() {
+ 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..dcb1958df 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/ChunkRaw.java
@@ -5,24 +5,51 @@ 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
+ /**
+ * @param len
+ * : data len
+ * @param idbytes
+ * : chunk type (deep copied)
+ * @param alloc
+ * : it true, the data array will be allocced
+ */
public ChunkRaw(int len, byte[] idbytes, boolean alloc) {
this.len = len;
System.arraycopy(idbytes, 0, this.idbytes, 0, 4);
@@ -30,54 +57,60 @@ public class ChunkRaw {
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() {
+ 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(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(InputStream is, boolean checkCrc) {
+ PngHelperInternal.readBytes(is, data, 0, len);
+ crcval = PngHelperInternal.readInt4(is);
+ if (checkCrc) {
+ 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..75107d761
--- /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(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() {
+ HashMap<String, Integer> ck = new HashMap<String, Integer>();
+ for (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(PngChunk c) {
+ return c.id.equals(id);
+ }
+ });
+ else
+ return ChunkHelper.filterList(list, new ChunkPredicate() {
+ @Override
+ public boolean match(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(PngChunk chunk, 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) {
+ 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(PngChunk c) {
+ return ChunkHelper.equivalent(c, c2);
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return "ChunkList: read: " + chunks.size();
+ }
+
+ /**
+ * for debugging
+ */
+ public String toStringFull() {
+ StringBuilder sb = new StringBuilder(toString());
+ sb.append("\n Read:\n");
+ for (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..c502e9071
--- /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 HashMap<String, Integer> alreadyWrittenKeys = new HashMap<String, Integer>();
+
+ public ChunksListForWrite(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) {
+ 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(PngChunk c) {
+ return queuedChunks.remove(c);
+ }
+
+ /**
+ * Adds chunk to queue
+ *
+ * Does not check for duplicated or anything
+ *
+ * @param c
+ */
+ public boolean queue(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(PngChunk c, 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(OutputStream os, int currentGroup) {
+ int cont = 0;
+ Iterator<PngChunk> it = queuedChunks.iterator();
+ while (it.hasNext()) {
+ 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() {
+ StringBuilder sb = new StringBuilder(toString());
+ sb.append("\n Written:\n");
+ for (PngChunk chunk : chunks) {
+ sb.append(chunk).append(" G=" + chunk.getChunkGroup() + "\n");
+ }
+ if (!queuedChunks.isEmpty()) {
+ sb.append(" Queued:\n");
+ for (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..6cd86eb98 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,6 +110,35 @@ 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(String chunkId, Class<? extends PngChunk> chunkClass) {
+ factoryMap.put(chunkId, chunkClass);
+ }
+
+ /**
+ * 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(String id) {
+ return factoryMap.containsKey(id);
}
protected PngChunk(String id, ImageInfo imgInfo) {
@@ -55,29 +149,21 @@ 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;
- }
-
+ /**
+ * This factory creates the corresponding chunk and parses the raw chunk.
+ * This is used when reading.
+ */
public static PngChunk factory(ChunkRaw chunk, ImageInfo info) {
PngChunk c = factoryFromId(ChunkHelper.toString(chunk.idbytes), info);
- c.lenori = chunk.len;
- c.parseFromChunk(chunk);
+ c.length = chunk.len;
+ c.parseFromRaw(chunk);
return c;
}
+ /**
+ * Creates one new blank chunk of the corresponding type, according to
+ * factoryMap (PngChunkUNKNOWN if not known)
+ */
public static PngChunk factoryFromId(String cid, ImageInfo info) {
PngChunk chunk = null;
try {
@@ -87,66 +173,112 @@ public abstract class PngChunk {
chunk = constr.newInstance(info);
}
} catch (Exception e) {
- // this can happend for unkown chunks
+ // this can happen for unkown chunks
}
if (chunk == null)
chunk = new PngChunkUNKNOWN(cid, info);
return chunk;
}
- protected ChunkRaw createEmptyChunk(int len, boolean alloc) {
+ protected final ChunkRaw createEmptyChunk(int len, boolean alloc) {
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(T chunk, ImageInfo info) {
+ 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(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(boolean priority) {
+ this.priority = priority;
}
- /** mustGoBeforeXX/After must be overriden - only relevant for ancillary chunks */
- public boolean mustGoBeforeIDAT() {
- return false;
+ final void write(OutputStream os) {
+ 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(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..ea6235432 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkBKGD.java
@@ -1,14 +1,18 @@
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;
@@ -19,43 +23,38 @@ public class PngChunkBKGD extends PngChunk {
}
@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(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);
} 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);
}
}
@@ -71,7 +70,7 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set gray value (0-255 if bitdept=8)
- *
+ *
* @param gray
*/
public void setGray(int gray) {
@@ -88,7 +87,7 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set pallette index
- *
+ *
*/
public void setPaletteIndex(int i) {
if (!imgInfo.indexed)
@@ -104,7 +103,7 @@ public class PngChunkBKGD extends PngChunk {
/**
* Set rgb values
- *
+ *
*/
public void setRGB(int r, int g, int b) {
if (imgInfo.greyscale || imgInfo.indexed)
@@ -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..25a4bf2d6 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkCHRM.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;
-/*
+/**
+ * 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;
@@ -14,46 +19,41 @@ public class PngChunkCHRM extends PngChunk {
private double bluex, bluey;
public PngChunkCHRM(ImageInfo info) {
- super(ChunkHelper.cHRM, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ 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(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
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..74640746e 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkGAMA.java
@@ -1,42 +1,42 @@
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;
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = createEmptyChunk(4, true);
int g = (int) (gamma * 100000 + 0.5);
- PngHelper.writeInt4tobytes(g, c.data, 0);
+ PngHelperInternal.writeInt4tobytes(g, c.data, 0);
return c;
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(ChunkRaw chunk) {
if (chunk.len != 4)
throw new PngjException("bad chunk " + chunk);
- int g = PngHelper.readInt4fromBytes(chunk.data, 0);
+ int g = PngHelperInternal.readInt4fromBytes(chunk.data, 0);
gamma = ((double) g) / 100000.0;
}
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..6dc3fd9ec 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkHIST.java
@@ -1,50 +1,48 @@
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);
+ 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(ChunkRaw c) {
if (!imgInfo.indexed)
throw new PngjException("only indexed images accept a HIST chunk");
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;
}
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..399577d72 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkICCP.java
@@ -1,31 +1,32 @@
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;
+ super(ID, info);
}
@Override
- public boolean mustGoBeforePLTE() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_PLTE_AND_IDAT;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
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;
@@ -35,12 +36,12 @@ public class PngChunkICCP extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(ChunkRaw chunk) {
int pos0 = ChunkHelper.posNullByte(chunk.data);
- profileName = new String(chunk.data, 0, pos0, PngHelper.charsetLatin1);
+ profileName = new String(chunk.data, 0, pos0, PngHelperInternal.charsetLatin1);
int comp = (chunk.data[pos0 + 1] & 0xff);
if (comp != 0)
- throw new RuntimeException("bad compression for ChunkTypeICCP");
+ throw new PngjException("bad compression for ChunkTypeICCP");
int compdatasize = chunk.data.length - (pos0 + 2);
compressedProfile = new byte[compdatasize];
System.arraycopy(chunk.data, pos0 + 2, compressedProfile, 0, compdatasize);
@@ -64,7 +65,7 @@ public class PngChunkICCP extends PngChunk {
}
public void setProfileNameAndContent(String name, String profile) {
- setProfileNameAndContent(name, profile.getBytes(PngHelper.charsetLatin1));
+ 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..911513c0d 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIDAT.java
@@ -2,21 +2,36 @@ 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(ImageInfo i, int len, 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(ChunkRaw c) { // does nothing
}
@Override
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..fbec564d8 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkIEND.java
@@ -2,21 +2,33 @@ 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);
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = new ChunkRaw(0, ChunkHelper.b_IEND, false);
return c;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(ChunkRaw c) {
// this is not used
}
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..94bfedd38 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;
@@ -22,16 +28,21 @@ public class PngChunkIHDR extends PngChunk {
// http://www.w3.org/TR/PNG/#11IHDR
//
public PngChunkIHDR(ImageInfo info) {
- super(ChunkHelper.IHDR, info);
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
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,18 +53,18 @@ public class PngChunkIHDR extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(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);
+ 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
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..ab52d7c90 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkITXT.java
@@ -4,14 +4,17 @@ 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 = "";
@@ -19,24 +22,24 @@ public class PngChunkITXT extends PngChunkTextVar {
// http://www.w3.org/TR/PNG/#11iTXt
public PngChunkITXT(ImageInfo info) {
- super(ChunkHelper.iTXt, 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));
+ 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);
}
@@ -51,7 +54,7 @@ public class PngChunkITXT extends PngChunkTextVar {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(ChunkRaw c) {
int nullsFound = 0;
int[] nullsIdx = new int[3];
for (int i = 0; i < c.data.length; i++) {
@@ -66,20 +69,21 @@ 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);
+ 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);
}
}
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..057f6c25e
--- /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(String id, 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..a3bab4995
--- /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(ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ 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(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(PngChunk other) {
+ 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(int units) {
+ this.units = units;
+ }
+
+ public long getPosX() {
+ return posX;
+ }
+
+ public void setPosX(long posX) {
+ this.posX = posX;
+ }
+
+ public long getPosY() {
+ return posY;
+ }
+
+ public void setPosY(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..b0a1bb898 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkPHYS.java
@@ -1,44 +1,50 @@
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);
+ super(ID, info);
}
@Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
ChunkRaw c = createEmptyChunk(9, true);
- PngHelper.writeInt4tobytes((int) pixelsxUnitX, c.data, 0);
- PngHelper.writeInt4tobytes((int) pixelsxUnitY, c.data, 4);
+ 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(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
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..dbf5e53c0 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;
/**
@@ -15,11 +21,16 @@ public class PngChunkPLTE extends PngChunk {
private int[] entries;
public PngChunkPLTE(ImageInfo info) {
- super(ChunkHelper.PLTE, info);
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NA;
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkRaw createRawChunk() {
int len = 3 * nentries;
int[] rgb = new int[3];
ChunkRaw c = createEmptyChunk(len, true);
@@ -33,7 +44,7 @@ public class PngChunkPLTE extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(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));
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..3a490654a 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);
+ 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(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) {
@@ -106,7 +106,7 @@ public class PngChunkSBIT extends PngChunk {
/**
* Set rgb values
- *
+ *
*/
public void setRGB(int r, int g, int b) {
if (imgInfo.greyscale || imgInfo.indexed)
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..2ff65834d 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkSPLT.java
@@ -4,11 +4,17 @@ 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;
@@ -16,35 +22,30 @@ public class PngChunkSPLT extends PngChunk {
private int[] palette; // 5 elements per entry
public PngChunkSPLT(ImageInfo info) {
- super(ChunkHelper.sPLT, 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));
+ ba.write(palName.getBytes(PngHelperInternal.charsetLatin1));
ba.write(0); // separator
ba.write((byte) sampledepth);
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);
@@ -56,7 +57,7 @@ public class PngChunkSPLT extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(ChunkRaw c) {
int t = -1;
for (int i = 0; i < c.data.length; i++) { // look for first zero
if (c.data[i] == 0) {
@@ -66,8 +67,8 @@ 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);
palette = new int[nentries * 5];
@@ -75,21 +76,21 @@ public class PngChunkSPLT extends PngChunk {
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;
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..e4d77d40a 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;
@@ -17,28 +22,23 @@ public class PngChunkSRGB extends PngChunk {
private int intent;
public PngChunkSRGB(ImageInfo info) {
- super(ChunkHelper.sRGB, info);
- }
-
- @Override
- public boolean mustGoBeforeIDAT() {
- return true;
+ 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(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;
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..4dc5edec5
--- /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(ImageInfo info) {
+ super(ID, info);
+ }
+
+ @Override
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.BEFORE_IDAT;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
+ ChunkRaw c = createEmptyChunk(1, true);
+ c.data[0] = (byte) mode;
+ return c;
+ }
+
+ @Override
+ public void parseFromRaw(ChunkRaw chunk) {
+ if (chunk.len != 1)
+ throw new PngjException("bad chunk length " + chunk);
+ mode = chunk.data[0];
+ }
+
+ @Override
+ public void cloneDataFromRead(PngChunk other) {
+ 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(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..7df5ba021
--- /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(String id, 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(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ 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..f4c77b4e1
--- /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(String id, ImageInfo info, 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(ChunkRaw c) {
+ throw new PngjException("Non supported for a skipped chunk");
+ }
+
+ @Override
+ public void cloneDataFromRead(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..d97cd63c5 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkTEXT.java
@@ -1,28 +1,40 @@
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 final static String ID = ChunkHelper.tEXt;
+
public PngChunkTEXT(ImageInfo info) {
- super(ChunkHelper.tEXt, info);
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
- if (val.isEmpty() || key.isEmpty())
- return null;
- byte[] b = (key + "\0" + val).getBytes(PngHelper.charsetLatin1);
+ public ChunkRaw createRawChunk() {
+ if (key.isEmpty())
+ throw new PngjException("Text chunk key must be non empty");
+ byte[] b = (key + "\0" + val).getBytes(PngHelperInternal.charsetLatin1);
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(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
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..8f34c78fe 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);
+ super(ID, info);
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
ChunkRaw c = createEmptyChunk(7, true);
- PngHelper.writeInt2tobytes(year, c.data, 0);
+ PngHelperInternal.writeInt2tobytes(year, c.data, 0);
c.data[2] = (byte) mon;
c.data[3] = (byte) day;
c.data[4] = (byte) hour;
@@ -28,15 +39,15 @@ public class PngChunkTIME extends PngChunk {
}
@Override
- public void parseFromChunk(ChunkRaw chunk) {
+ public void parseFromRaw(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
@@ -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..867e34861 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(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(ChunkRaw c) {
+ if (imgInfo.greyscale) {
+ gray = PngHelperInternal.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 = PngHelperInternal.readInt2fromBytes(c.data, 0);
+ green = PngHelperInternal.readInt2fromBytes(c.data, 2);
+ blue = PngHelperInternal.readInt2fromBytes(c.data, 4);
+ }
+ }
+
+ @Override
+ public void cloneDataFromRead(PngChunk other) {
+ 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(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;
+ }
+
+ /**
+ * to use when only one pallete index is set as totally transparent
+ */
+ public void setIndexEntryAsTransparent(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..ba3ffc30c 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;
@@ -28,8 +26,8 @@ public abstract class PngChunkTextVar extends PngChunk {
}
@Override
- public boolean allowsMultiple() {
- return true;
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
}
public static class PngTxtInfo {
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..3803428e6 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkUNKNOWN.java
@@ -2,7 +2,12 @@ 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;
@@ -10,25 +15,25 @@ public class PngChunkUNKNOWN extends PngChunk { // unkown, custom or not
super(id, info);
}
- @Override
- public boolean allowsMultiple() {
- return true;
- }
-
private PngChunkUNKNOWN(PngChunkUNKNOWN c, ImageInfo info) {
super(c.id, info);
System.arraycopy(c.data, 0, data, 0, c.data.length);
}
@Override
- public ChunkRaw createChunk() {
+ public ChunkOrderingConstraint getOrderingConstraint() {
+ return ChunkOrderingConstraint.NONE;
+ }
+
+ @Override
+ public ChunkRaw createRawChunk() {
ChunkRaw p = createEmptyChunk(data.length, false);
p.data = this.data;
return p;
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(ChunkRaw c) {
data = c.data;
}
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..64593eae4 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngChunkZTXT.java
@@ -4,26 +4,32 @@ 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);
+ 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));
+ 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);
+ byte[] textbytes = ChunkHelper.compressBytes(val.getBytes(PngHelperInternal.charsetLatin1), true);
ba.write(textbytes);
byte[] b = ba.toByteArray();
ChunkRaw chunk = createEmptyChunk(b.length, false);
@@ -35,7 +41,7 @@ public class PngChunkZTXT extends PngChunkTextVar {
}
@Override
- public void parseFromChunk(ChunkRaw c) {
+ public void parseFromRaw(ChunkRaw c) {
int nullsep = -1;
for (int i = 0; i < c.data.length; i++) { // look for first zero
if (c.data[i] != 0)
@@ -45,12 +51,12 @@ 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);
+ key = new String(c.data, 0, nullsep, PngHelperInternal.charsetLatin1);
int compmet = (int) 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);
+ val = new String(uncomp, PngHelperInternal.charsetLatin1);
}
@Override
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..139603448 100644
--- a/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
+++ b/src/jogl/classes/jogamp/opengl/util/pngj/chunks/PngMetadata.java
@@ -1,68 +1,72 @@
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(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, boolean lazyOverwrite) {
+ 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(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);
+ PngChunk c = chunkList.getById1(ChunkHelper.pHYs, true);
if (c == null)
return new double[] { -1, -1 };
else
@@ -76,31 +80,71 @@ public class PngMetadata {
public void setDpi(double x, double y) {
PngChunkPHYS c = new PngChunkPHYS(chunkList.imageInfo);
c.setAsDpi2(x, y);
- setChunk(c, true);
+ queueChunk(c);
}
// //////////// TIME
- public void setTimeNow(int secsAgo) {
+ /**
+ * 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(int secsAgo) {
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) {
+ /**
+ * 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(int yearx, int monx, int dayx, int hourx, int minx, int secx) {
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() : "";
+ 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(String k, String val, boolean useLatin1, boolean compress) {
if (compress && !useLatin1)
throw new PngjException("cannot compress non latin text");
PngChunkTextVar c;
@@ -115,21 +159,83 @@ 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(String k, String val) {
+ return setText(k, val, false, false);
}
- /** tries all text chunks - returns null if not found */
+ /**
+ * 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(String k) {
+ @SuppressWarnings("rawtypes")
+ 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(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;
+ List<? extends PngChunkTextVar> li = getTxtsForKey(k);
+ if (li.isEmpty())
+ return "";
+ StringBuilder t = new StringBuilder();
+ for (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() {
+ 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() {
+ 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/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index 5ff63d93b..feacdb951 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;
@@ -52,6 +54,7 @@ public class WGLGLCapabilities extends GLCapabilities {
public boolean setValuesByGDI() {
arb_pixelformat = -1;
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
setRedBits(pfd.getCRedBits());
setGreenBits(pfd.getCGreenBits());
setBlueBits(pfd.getCBlueBits());
@@ -62,10 +65,11 @@ public class WGLGLCapabilities extends GLCapabilities {
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
@@ -74,11 +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(PIXELFORMATDESCRIPTOR pfd, int pfdID) {
+ final int dwFlags = pfd.getDwFlags();
+ 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:
@@ -86,101 +128,99 @@ 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:
- setAlphaBits(iresults[i]);
+ // ALPHA shall be set at last - due to it's auto setting by !opaque / samples
+ 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);
return true;
}
+ @Override
public Object cloneMutable() {
return clone();
}
+ @Override
public Object clone() {
try {
return super.clone();
@@ -191,11 +231,11 @@ public class WGLGLCapabilities extends GLCapabilities {
final public PIXELFORMATDESCRIPTOR getPFD() { return pfd; }
final public int getPFDID() { return pfdID; }
-
+
final public boolean isSetByARB() { return 0 < arb_pixelformat; }
final public boolean isSetByGDI() { return 0 > arb_pixelformat; }
final public boolean isSet() { return 0 != arb_pixelformat; }
-
+
@Override
final public int getVisualID(VIDType type) throws NativeWindowException {
switch(type) {
@@ -205,16 +245,17 @@ public class WGLGLCapabilities extends GLCapabilities {
return getPFDID();
default:
throw new NativeWindowException("Invalid type <"+type+">");
- }
+ }
}
-
+
+ @Override
public StringBuilder toString(StringBuilder sink) {
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:
+ case -1:
sink.append("gdi");
break;
case 0:
@@ -229,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..6454a34b5 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLUtil.java
@@ -33,15 +33,15 @@ 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,8 +49,9 @@ public class WGLUtil {
* @see jogamp.nativewindow.windows.GDI#SwapBuffers(long)
*/
public static final boolean USE_WGLVersion_Of_5WGLGDIFuncSet;
-
+
static {
+ Debug.initSingleton();
USE_WGLVersion_Of_5WGLGDIFuncSet = Debug.isPropertyDefined("jogl.windows.useWGLVersionOf5WGLGDIFuncSet", true);
if(USE_WGLVersion_Of_5WGLGDIFuncSet) {
System.err.println("Use WGL version of 5 WGL/GDI functions.");
@@ -62,34 +63,34 @@ public class WGLUtil {
return WGL.wglChoosePixelFormat(hdc, pfd);
} else {
return GDI.ChoosePixelFormat(hdc, pfd);
- }
+ }
}
public static int DescribePixelFormat(long hdc, int pfdid, int pfdSize, 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) {
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(long hdc, int pfdid, 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(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 68b26b30d..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
+++ /dev/null
@@ -1,64 +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);
- }
-
- public int getOffscreenContextPixelDataType() {
- return GL.GL_UNSIGNED_BYTE;
- }
-
- public int getOffscreenContextReadBuffer() {
- // On Windows these contexts are always single-buffered
- return GL.GL_FRONT;
- }
-
- 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 574226570..f658a3598 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.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,41 +29,62 @@
* 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 com.jogamp.common.nio.PointerBuffer;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.SurfaceChangeable;
+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 javax.media.opengl.GLCapabilitiesImmutable;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+
+import com.jogamp.common.nio.PointerBuffer;
public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
private long origbitmap;
private long hbitmap;
- protected WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
- super(factory, target, false);
+ private WindowsBitmapWGLDrawable(GLDrawableFactory factory, NativeSurface comp) {
+ super(factory, comp, false);
}
- protected void destroyImpl() {
- setRealized(false);
+ protected static WindowsBitmapWGLDrawable create(GLDrawableFactory factory, 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
protected void setRealizedImpl() {
if(realized) {
createBitmap();
@@ -72,35 +93,44 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsBitmapWGLContext(this, 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 = getWidth();
+ final int height = getHeight();
//
// 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);
@@ -109,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;
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) {
@@ -140,9 +170,9 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
hbitmap = 0;
throw new GLException("Error creating device context for offscreen OpenGL context, werr "+werr);
}
- ((SurfaceChangeable)ns).setSurfaceHandle(hdc);
+ ((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) {
@@ -152,10 +182,10 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
hdc = 0;
throw new GLException("Error selecting bitmap into new device context");
}
-
+
config.updateGraphicsConfiguration(getFactory(), ns, null);
}
-
+
protected void destroyBitmap() {
NativeSurface ns = getNativeSurface();
if (ns.getSurfaceHandle() != 0) {
@@ -165,7 +195,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
GDI.DeleteDC(ns.getSurfaceHandle());
origbitmap = 0;
hbitmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
deleted file mode 100644
index 3ba5508ab..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java
+++ /dev/null
@@ -1,105 +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.GLContext;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-
-import javax.media.nativewindow.AbstractGraphicsScreen;
-import jogamp.nativewindow.windows.GDI;
-import jogamp.nativewindow.windows.GDIUtil;
-
-import javax.media.nativewindow.NativeSurface;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLException;
-import jogamp.nativewindow.windows.GDISurface;
-
-public class WindowsDummyWGLDrawable extends WindowsWGLDrawable {
- private long hwnd;
- private boolean handleHwndLifecycle;
-
- private WindowsDummyWGLDrawable(GLDrawableFactory factory, GDISurface ns, boolean handleHwndLifecycle) {
- super(factory, ns, true);
- this.handleHwndLifecycle = handleHwndLifecycle;
-
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= ns.lockSurface()) {
- throw new GLException("WindowsDummyWGLDrawable: surface not ready (lockSurface)");
- }
- try {
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
- config.updateGraphicsConfiguration(factory, ns, null);
- if (DEBUG) {
- System.err.println("WindowsDummyWGLDrawable: "+config);
- }
- } catch (Throwable t) {
- destroyImpl();
- throw new GLException(t);
- } finally {
- unlockSurface();
- }
- }
-
- public static WindowsDummyWGLDrawable create(GLDrawableFactory factory, GLProfile glp, AbstractGraphicsScreen absScreen,
- long windowHandle, int width, int height, boolean handleWindowLifecycle) {
- if(0 == windowHandle) {
- throw new GLException("Error windowHandle 0, werr: "+GDI.GetLastError());
- }
- GLCapabilities caps = new GLCapabilities(glp);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(caps, absScreen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- ns.surfaceSizeChanged(width, height);
- return new WindowsDummyWGLDrawable(factory, ns, handleWindowLifecycle);
- }
-
- public GLContext createContext(GLContext shareWith) {
- // FIXME: figure out how to hook back in the Java 2D / JOGL bridge
- return new WindowsWGLContext(this, shareWith);
- }
-
- protected void destroyImpl() {
- if (handleHwndLifecycle && hwnd != 0) {
- GDI.ShowWindow(hwnd, GDI.SW_HIDE);
- GDIUtil.DestroyDummyWindow(hwnd);
- hwnd = 0;
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index 745782085..c46b3c9dd 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.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.
*/
@@ -50,14 +50,11 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import com.jogamp.nativewindow.WrappedSurface;
-
+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) {
super(drawable, null);
@@ -66,7 +63,9 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
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
}
@@ -103,32 +102,18 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
System.err.println("WindowsExternalWGLContext valid hdc/pfd, retrieved cfg: " + cfg);
}
}
- return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc)), ctx, cfg);
- }
-
- 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();
- }
-
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
+ return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)), ctx, cfg);
}
+ @Override
protected void makeCurrentImpl() throws GLException {
}
+ @Override
protected void releaseImpl() throws GLException {
}
+ @Override
protected void destroyImpl() throws GLException {
}
@@ -138,14 +123,17 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
super(factory, comp, true);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
throw new GLException("Should not call this");
}
+ @Override
public int getWidth() {
throw new GLException("Should not call this");
}
+ @Override
public int getHeight() {
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 ad2e91bed..f8c237c9e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.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.
*/
@@ -49,9 +49,10 @@ import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import com.jogamp.nativewindow.WrappedSurface;
-
+import jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
+import jogamp.nativewindow.windows.GDIUtil;
+
public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
@@ -69,25 +70,28 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable {
throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat, werr " + GDI.GetLastError());
}
- AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
- return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc));
+ final AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
+ final WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.createFromExternal(factory, hdc, pfdID, glp, aScreen, true);
+ return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true));
}
+ @Override
public GLContext createContext(GLContext shareWith) {
return new WindowsWGLContext(this, shareWith);
}
-
+
public void setSize(int newWidth, int newHeight) {
throw new GLException("Should not call this");
}
+ @Override
public int getWidth() {
throw new GLException("Should not call this");
- }
+ }
+ @Override
public int getHeight() {
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 a06ab8f0e..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
+++ /dev/null
@@ -1,53 +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 java.util.*;
-
-import javax.media.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.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 6ad330ccc..61fb787c6 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.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.windows.wgl;
-import javax.media.nativewindow.*;
-import javax.media.opengl.*;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable {
protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeSurface component) {
super(factory, component, false);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsOnscreenWGLContext(this, 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 0f610495d..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ /dev/null
@@ -1,150 +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 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);
- }
-
- 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().
- }
-
- 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());
- }
- }
- }
-
- 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("GL_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 = GL2.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;
- }
-
- 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 0988f3eca..2e60c682b 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.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,48 +29,47 @@
* 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 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.SurfaceChangeable;
-import javax.media.opengl.GL;
+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 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.GLCapabilitiesImmutable;
-
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) {
super(factory, target, false);
}
- protected void destroyImpl() {
- setRealized(false);
- }
-
+ @Override
protected void setRealizedImpl() {
if(realized) {
createPbuffer();
@@ -79,8 +78,9 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsPbufferWGLContext(this, shareWith);
+ return new WindowsWGLContext(this, shareWith);
}
protected void destroyPbuffer() {
@@ -95,7 +95,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
if (wglExt.wglReleasePbufferDCARB(buffer, ns.getSurfaceHandle()) == 0) {
throw new GLException("Error releasing pbuffer device context: error code " + GDI.GetLastError());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
}
if (!wglExt.wglDestroyPbufferARB(buffer)) {
throw new GLException("Error destroying pbuffer: error code " + GDI.GetLastError());
@@ -111,139 +111,106 @@ 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());
+ SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
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 = sharedResource.getContext().getWGLExt();
-
+ WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt();
+
if (DEBUG) {
- System.out.println("Pbuffer config: " + config);
+ System.out.println(getThreadName()+": Pbuffer config: " + config);
}
-
- int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS];
- float[] fattributes = new float[1];
+
+ final int winattrPbuffer = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(false /* onscreen */, false /* fbo */, true /* pbuffer */, false /* bitmap */);
+
+ final IntBuffer iattributes = Buffers.newDirectIntBuffer(2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS);
+ final FloatBuffer fattributes = Buffers.newDirectFloatBuffer(1);
int[] floatModeTmp = new int[1];
int niattribs = 0;
- int width, height;
-
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
- GLProfile glProfile = chosenCaps.getGLProfile();
-
+
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ final GLProfile glProfile = chosenCaps.getGLProfile();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+
if (DEBUG) {
- System.out.println("Pbuffer parentHdc = " + toHexString(sharedHdc));
- System.out.println("Pbuffer chosenCaps: " + chosenCaps);
+ System.out.println(getThreadName()+": Pbuffer parentHdc = " + toHexString(sharedHdc));
+ System.out.println(getThreadName()+": Pbuffer chosenCaps: " + chosenCaps);
}
-
+
if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps,
iattributes, sharedResource, -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");
}
-
+
if (DEBUG) {
System.err.println("" + nformats + " suitable pixel formats found");
for (int i = 0; i < nformats; i++) {
- WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, sharedHdc, pformats[i], glProfile, false, true);
- System.err.println("pixel format " + pformats[i] + " (index " + i + "): " + dbgCaps);
+ WGLGLCapabilities dbgCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, device, glProfile,
+ sharedHdc, pformats.get(i), winattrPbuffer);
+ System.err.println("pixel format " + pformats.get(i) + " (index " + i + "): " + dbgCaps);
}
}
-
+
int pfdid = 0;
long tmpBuffer = 0;
{
int whichFormat;
// Loop is a workaround for bugs in NVidia's recent drivers
for (whichFormat = 0; whichFormat < nformats; whichFormat++) {
- int format = pformats[whichFormat];
-
+ 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;
- iattributes[niattribs++] = GL.GL_FALSE;
- }
-
- iattributes[niattribs++] = 0;
-
- tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes, 0);
+
+ iattributes.put(niattribs++, 0);
+
+ tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes);
if (tmpBuffer != 0) {
// Done
break;
}
}
-
+
if (0 == tmpBuffer) {
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);
if (tmpHdc == 0) {
throw new GLException("pbuffer creation error: wglGetPbufferDC() failed");
}
-
+
NativeSurface ns = getNativeSurface();
// Set up instance variables
buffer = tmpBuffer;
- ((SurfaceChangeable)ns).setSurfaceHandle(tmpHdc);
- cachedWGLExt = wglExt;
-
+ ((MutableSurface)ns).setSurfaceHandle(tmpHdc);
+ cachedWGLExt = wglExt;
+
// Re-query chosen pixel format
{
- WGLGLCapabilities newCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, sharedHdc, pfdid, glProfile, false, true);
+ 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));
}
@@ -252,14 +219,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
}
config.setCapsPFD(newCaps);
}
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 );
- width = tmp[0];
- wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 );
- height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
} finally {
sharedSurface.unlockSurface();
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 217d88f3c..b214252c1 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.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.opengl.windows.wgl;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -51,8 +52,12 @@ import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
import javax.media.opengl.GLCapabilitiesImmutable;
+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;
import jogamp.opengl.GLDrawableImpl;
@@ -77,8 +82,8 @@ public class WindowsWGLContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format");
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, WindowsWGLDrawableFactory.WGL_ARB_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, WindowsWGLDrawableFactory.WGL_ARB_pixel_format);
}
// FIXME: figure out how to hook back in the Java 2D / JOGL bridge
@@ -88,7 +93,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
@Override
- protected void resetStates() {
+ protected void resetStates(boolean isInit) {
wglGetExtensionsStringEXTInitialized=false;
wglGetExtensionsStringEXTAvailable=false;
wglGLReadDrawableAvailableSet=false;
@@ -96,10 +101,11 @@ public class WindowsWGLContext extends GLContextImpl {
// no inner state _wglExt=null;
wglExtProcAddressTable=null;
hasSwapIntervalSGI = 0;
- hasSwapGroupNV = 0;
- super.resetStates();
+ hasSwapGroupNV = 0;
+ super.resetStates(isInit);
}
-
+
+ @Override
public Object getPlatformGLExtensions() {
return getWGLExt();
}
@@ -114,6 +120,7 @@ public class WindowsWGLContext extends GLContextImpl {
return _wglExt;
}
+ @Override
public final boolean isGLReadDrawableAvailable() {
if(!wglGLReadDrawableAvailableSet && null != getWGLExtProcAddressTable()) {
WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
@@ -159,6 +166,7 @@ public class WindowsWGLContext extends GLContextImpl {
return ok;
}
+ @Override
public final ProcAddressTable getPlatformExtProcAddressTable() {
return getWGLExtProcAddressTable();
}
@@ -167,15 +175,19 @@ public class WindowsWGLContext extends GLContextImpl {
return wglExtProcAddressTable;
}
+ @Override
protected Map<String, String> getFunctionNameMap() { return functionNameMap; }
+ @Override
protected Map<String, String> getExtensionNameMap() { return extensionNameMap; }
+ @Override
protected void destroyContextARBImpl(long context) {
WGL.wglMakeCurrent(0, 0);
WGL.wglDeleteContext(context);
}
+ @Override
protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
if( null == getWGLExtProcAddressTable()) {
updateGLXProcAddressTable();
@@ -207,14 +219,13 @@ 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;
} else {
attribs[idx_profile+1] = WGLExt.WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
- }
- }
+ }
+ }
if ( major >= 3 ) {
if( !ctBwdCompat && ctFwdCompat ) {
@@ -226,7 +237,8 @@ public class WindowsWGLContext extends GLContextImpl {
}
try {
- ctx = _wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribs, 0);
+ final IntBuffer attribsNIO = Buffers.newDirectIntBuffer(attribs);
+ ctx = _wglExt.wglCreateContextAttribsARB(drawable.getHandle(), share, attribsNIO);
} catch (RuntimeException re) {
if(DEBUG) {
Throwable t = new Throwable("Info: WindowWGLContext.createContextARBImpl wglCreateContextAttribsARB failed with "+getGLVersion(major, minor, ctp, "@creation"), re);
@@ -255,74 +267,92 @@ public class WindowsWGLContext extends GLContextImpl {
* Creates and initializes an appropriate OpenGL context. Should only be
* called by {@link #makeCurrentImpl()}.
*/
- 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();
+ @Override
+ 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 */, false /* 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");
+ 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 ) {
// 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);
}
}
+ } 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)) {
@@ -330,10 +360,10 @@ public class WindowsWGLContext extends GLContextImpl {
}
}
} else {
- if(glCaps.getGLProfile().isGL3()) {
+ if( glCaps.getGLProfile().isGL3() ) {
WGL.wglMakeCurrent(0, 0);
WGL.wglDeleteContext(temp_ctx);
- throw new GLException("WindowsWGLContext.createContext ctx !ARB, context > GL2 requested "+getGLVersion());
+ throw new GLException(getThreadName()+": WindowsWGLContex.createContextImpl ctx !ARB, 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());
@@ -341,41 +371,49 @@ public class WindowsWGLContext extends GLContextImpl {
// continue with temp context for GL < 3.0
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) {
- // Only utilize the classic GDI 'wglShareLists' shared context method
+ 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));
}
}
return true;
}
-
+
+ @Override
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);
}
}
}
+ @Override
protected void releaseImpl() throws GLException {
if (!wglMakeContextCurrent(0, 0, 0)) {
throw new GLException("Error freeing OpenGL context, werr: " + GDI.GetLastError());
}
}
+ @Override
protected void destroyImpl() throws GLException {
WGL.wglMakeCurrent(0, 0);
if (!WGL.wglDeleteContext(contextHandle)) {
@@ -383,12 +421,14 @@ public class WindowsWGLContext extends GLContextImpl {
}
}
+ @Override
protected void copyImpl(GLContext source, int mask) throws GLException {
if (!WGL.wglCopyContext(source.getHandle(), getHandle(), mask)) {
throw new GLException("wglCopyContext failed");
}
}
+ @Override
protected final void updateGLXProcAddressTable() {
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
@@ -421,10 +461,11 @@ public class WindowsWGLContext extends GLContextImpl {
}
}
}
-
+
+ @Override
protected final StringBuilder getPlatformExtensionsStringImpl() {
StringBuilder sb = new StringBuilder();
-
+
if (!wglGetExtensionsStringEXTInitialized) {
wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0);
wglGetExtensionsStringEXTInitialized = true;
@@ -434,7 +475,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
return sb;
}
-
+
@Override
protected boolean setSwapIntervalImpl(int interval) {
WGLExt wglExt = getWGLExt();
@@ -450,7 +491,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
return false;
}
-
+
private final int initSwapGroupImpl(WGLExt wglExt) {
if(0==hasSwapGroupNV) {
try {
@@ -462,7 +503,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
return hasSwapGroupNV;
}
-
+
@Override
protected final boolean queryMaxSwapGroupsImpl(int[] maxGroups, int maxGroups_offset,
int[] maxBarriers, int maxBarriers_offset) {
@@ -471,16 +512,19 @@ public class WindowsWGLContext extends GLContextImpl {
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; }
}
return res;
}
-
+
@Override
protected final boolean joinSwapGroupImpl(int group) {
boolean res = false;
@@ -495,7 +539,7 @@ public class WindowsWGLContext extends GLContextImpl {
}
return res;
}
-
+
@Override
protected final boolean bindSwapBarrierImpl(int group, int barrier) {
boolean res = false;
@@ -507,31 +551,17 @@ public class WindowsWGLContext extends GLContextImpl {
}
} catch (Throwable t) { hasSwapGroupNV=-1; }
}
- return res;
- }
-
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
- }
-
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
+ return res;
}
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
+ @Override
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
+ return getWGLExt().wglAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
+ @Override
+ public final void glFreeMemoryNV(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 579b11940..66071cbe1 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.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.
*/
@@ -51,7 +51,13 @@ 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 = Debug.isPropertyDefined("jogl.debug.GLDrawable.profiling", true);
+ }
+
private static final int PROFILING_TICKS = 200;
private int profilingSwapBuffersTicks;
private long profilingSwapBuffersTime;
@@ -60,43 +66,45 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl {
super(factory, comp, realized);
}
+ @Override
protected void setRealizedImpl() {
- if(!realized) {
- return; // nothing todo ..
- }
-
- NativeSurface ns = getNativeSurface();
- WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
- config.updateGraphicsConfiguration(getFactory(), ns, null);
- if (DEBUG) {
- System.err.println("WindowsWGLDrawable.setRealized(true): "+config);
+ if(realized) {
+ NativeSurface ns = getNativeSurface();
+ WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration();
+ config.updateGraphicsConfiguration(getFactory(), ns, null);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": WindowsWGLDrawable.setRealized(true): "+config);
+ }
}
}
- protected final void swapBuffersImpl() {
- // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- final long t0;
- if (PROFILING) {
- t0 = System.currentTimeMillis();
- } else {
- t0 = 0;
- }
+ @Override
+ protected final void swapBuffersImpl(boolean doubleBuffered) {
+ if(doubleBuffered) {
+ final long t0;
+ if (PROFILING) {
+ t0 = System.currentTimeMillis();
+ } else {
+ t0 = 0;
+ }
- if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) {
- throw new GLException("Error swapping buffers");
- }
+ 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) {
- System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" +
- ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)");
- profilingSwapBuffersTime = 0;
- profilingSwapBuffersTicks = 0;
- }
+ if (PROFILING) {
+ profilingSwapBuffersTime += System.currentTimeMillis() - t0;
+ if (++profilingSwapBuffersTicks == PROFILING_TICKS) {
+ System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" +
+ ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)");
+ profilingSwapBuffersTime = 0;
+ profilingSwapBuffersTicks = 0;
+ }
+ }
}
}
+ @Override
public GLDynamicLookupHelper getGLDynamicLookupHelper() {
return getFactoryImpl().getGLDynamicLookupHelper(0);
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 494bb307e..7fa8775cf 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.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,82 +42,90 @@ 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;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindowFactory;
-import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GL;
-import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import javax.media.opengl.GLProfile.ShutdownType;
-
-import com.jogamp.common.JogampRuntimeException;
-import com.jogamp.common.nio.PointerBuffer;
-import com.jogamp.common.os.Platform;
-import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.VersionNumber;
-import com.jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.windows.GDI;
-import jogamp.nativewindow.windows.GDIUtil;
+import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook;
import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+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.nio.PointerBuffer;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
+
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
-
+
public WindowsWGLDrawableFactory() {
super();
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 (Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- windowsWGLDynamicLookupHelper = tmp;
- WGL.getWGLProcAddressTable().reset(windowsWGLDynamicLookupHelper);
- }
+ } );
}
}
-
+
defaultDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
-
+
if(null!=windowsWGLDynamicLookupHelper) {
// Register our GraphicsConfigurationFactory implementations
// The act of constructing them causes them to be registered
WindowsWGLGraphicsConfigurationFactory.registerFactory();
if(GLProfile.isAWTAvailable()) {
try {
- ReflectionUtil.callStaticMethod("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory",
- "registerFactory", null, null, getClass().getClassLoader());
- } catch (JogampRuntimeException jre) { /* n/a .. */ }
+ ReflectionUtil.callStaticMethod("jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory",
+ "registerFactory", null, null, getClass().getClassLoader());
+ } catch (Exception jre) { /* n/a .. */ }
}
-
+
sharedMap = new HashMap<String, SharedResourceRunner.Resource>();
-
+
// Init shared resources off thread
// Will be released via ShutdownHook
sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation());
@@ -125,7 +133,17 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
- protected final void destroy(ShutdownType shutdownType) {
+ @Override
+ protected final boolean isComplete() {
+ return null != windowsWGLDynamicLookupHelper;
+ }
+
+
+ @Override
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("WindowsWGLDrawableFactory.shutdown");
+ }
if(null != sharedResourceRunner) {
sharedResourceRunner.stop();
sharedResourceRunner = null;
@@ -137,15 +155,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
defaultDevice = null;
/**
* Pulling away the native library may cause havoc ..
- *
- if(ShutdownType.COMPLETE == shutdownType && null != windowsWGLDynamicLookupHelper) {
- windowsWGLDynamicLookupHelper.destroy();
- windowsWGLDynamicLookupHelper = null;
- } */
-
+ *
+ windowsWGLDynamicLookupHelper.destroy();
+ */
+ windowsWGLDynamicLookupHelper = null;
+
RegisteredClassFactory.shutdownSharedClasses();
}
+ @Override
public GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
return windowsWGLDynamicLookupHelper;
}
@@ -155,16 +173,17 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap;
private long processAffinityChanges = 0;
- private PointerBuffer procMask = PointerBuffer.allocateDirect(1);
- private PointerBuffer sysMask = PointerBuffer.allocateDirect(1);
+ private final PointerBuffer procMask = PointerBuffer.allocateDirect(1);
+ private final 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());
+ System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
// Thread.dumpStack();
}
processAffinityChanges = pid;
@@ -174,6 +193,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
protected void leaveThreadCriticalZone() {
synchronized (sysMask) {
if( 0 != processAffinityChanges) {
@@ -183,35 +203,25 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
" this PID 0x" + Long.toHexString(pid) );
}
if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
+ System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
}
GDI.SetProcessAffinityMask(pid, sysMask.get(0));
}
}
}
- /**
- * 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 WindowsDummyWGLDrawable drawable;
- private WindowsWGLContext 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, WindowsDummyWGLDrawable draw, WindowsWGLContext ctx,
- boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
+ private GLDrawableImpl drawable;
+ private GLContextImpl context;
+
+ SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
+ boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable) {
device = dev;
screen = scrn;
drawable = draw;
@@ -220,90 +230,71 @@ 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; }
- final public WindowsWGLDrawable getDrawable() { return drawable; }
- final public WindowsWGLContext getContext() { return context; }
+ @Override
+ 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);
- }
+ return sharedMap.put(connection, resource);
}
+ @Override
public SharedResourceRunner.Resource mapGet(String connection) {
- synchronized(sharedMap) {
- return sharedMap.get(connection);
- }
+ return sharedMap.get(connection);
}
+ @Override
public Collection<SharedResourceRunner.Resource> mapValues() {
synchronized(sharedMap) {
return sharedMap.values();
}
}
+ @Override
+ public boolean isDeviceSupported(String connection) {
+ return true;
+ }
+
+ @Override
public SharedResourceRunner.Resource createSharedResource(String connection) {
- WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
+ final WindowsGraphicsDevice sharedDevice = new WindowsGraphicsDevice(connection, AbstractGraphicsDevice.DEFAULT_UNIT);
sharedDevice.lock();
try {
- AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
- GLProfile glp = GLProfile.get(sharedDevice, GLProfile.GL_PROFILE_LIST_MIN_DESKTOP, false);
+ final AbstractGraphicsScreen absScreen = new DefaultGraphicsScreen(sharedDevice, 0);
+ 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 int f_dim = 64;
- long hwnd = GDIUtil.CreateDummyWindow(0, 0, f_dim, f_dim);
- WindowsDummyWGLDrawable sharedDrawable = WindowsDummyWGLDrawable.create(WindowsWGLDrawableFactory.this, glp, absScreen, hwnd, f_dim, f_dim, true);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+absScreen+", "+glp);
- }
- WindowsWGLContext sharedContext = (WindowsWGLContext) sharedDrawable.createContext(null);
+ 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);
}
@@ -311,15 +302,13 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
boolean hasARBMultisample;
boolean hasARBPBuffer;
boolean hasARBReadDrawableAvailable;
- String vendor;
sharedContext.makeCurrent();
try {
hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
hasARBMultisample = sharedContext.isExtensionAvailable(WGL_ARB_multisample);
- hasARBPBuffer = sharedContext.isExtensionAvailable(GL_ARB_pbuffer);
+ 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();
}
@@ -331,11 +320,10 @@ 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,
+ return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext,
hasARBPixelFormat, hasARBMultisample,
- hasARBPBuffer, hasARBReadDrawableAvailable, vendor);
+ hasARBPBuffer, hasARBReadDrawableAvailable);
} catch (Throwable t) {
throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t);
} finally {
@@ -343,6 +331,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
public void releaseSharedResource(SharedResourceRunner.Resource shared) {
SharedResource sr = (SharedResource) shared;
if (DEBUG) {
@@ -359,7 +348,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
if (null != sr.drawable) {
- sr.drawable.destroy();
+ sr.drawable.setRealized(false);
sr.drawable = null;
}
@@ -374,10 +363,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
public final AbstractGraphicsDevice getDefaultDevice() {
return defaultDevice;
}
+ @Override
public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
if(null!=windowsWGLDynamicLookupHelper && device instanceof WindowsGraphicsDevice) {
return true;
@@ -385,64 +376,37 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
- final static String GL_ARB_pbuffer = "GL_ARB_pbuffer";
+ final static String WGL_ARB_pbuffer = "WGL_ARB_pbuffer";
final static String WGL_ARB_pixel_format = "WGL_ARB_pixel_format";
final static String WGL_ARB_multisample = "WGL_ARB_multisample";
final static String WGL_NV_float_buffer = "WGL_NV_float_buffer";
final static String WGL_ARB_make_current_read = "WGL_ARB_make_current_read";
final static String wglMakeContextCurrent = "wglMakeContextCurrent";
+ @Override
protected final Thread getSharedResourceThread() {
return sharedResourceRunner.start();
}
-
- 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;
- }
-
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
- protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+ protected final WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
+ 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) {
return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
}
+ @Override
protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -450,6 +414,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return new WindowsOnscreenWGLDrawable(this, target);
}
+ @Override
protected final GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -457,7 +422,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
AbstractGraphicsConfiguration config = target.getGraphicsConfiguration();
GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
if(!chosenCaps.isPBuffer()) {
- return new WindowsBitmapWGLDrawable(this, target);
+ return WindowsBitmapWGLDrawable.create(this, target);
}
// PBuffer GLDrawable Creation
@@ -468,7 +433,7 @@ 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();
if (lastContext != null) {
@@ -494,46 +459,77 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
* 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);
+ SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasReadDrawable() ? 1 : 0 ;
}
return -1; // undefined
}
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+ @Override
+ public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
+ SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasARBPBuffer();
}
return false;
}
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) {
- AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
- WrappedSurface ns = new WrappedSurface(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- capsChosen, capsRequested, chooser, screen) );
- ns.surfaceSizeChanged(width, height);
- return ns;
+ @Override
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ final WindowsGraphicsDevice device;
+ if(createNewDevice || !(deviceReq instanceof WindowsGraphicsDevice)) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ 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);
+ }
+ return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) {
+ final WindowsGraphicsDevice device;
+ if( createNewDevice || !(deviceReq instanceof WindowsGraphicsDevice) ) {
+ device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID());
+ } else {
+ device = (WindowsGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ final WindowsWGLGraphicsConfiguration config = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(chosenCaps, requestedCaps, chooser, screen);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+chosenCaps+" on "+screen);
+ }
+ return new GDISurface(config, 0, new GDIDummyUpstreamSurfaceHook(width, height), createNewDevice);
}
-
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- WindowsGraphicsDevice device = (WindowsGraphicsDevice) adevice;
- AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
- WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- GDISurface ns = new GDISurface(cfg, windowHandle);
- return ns;
+
+ @Override
+ protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, 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);
+ return new GDISurface(cfg, windowHandle, upstream, true);
}
-
+
+ @Override
protected final GLContext createExternalGLContextImpl() {
return WindowsExternalWGLContext.create(this, null);
}
+ @Override
public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
return true;
}
+ @Override
protected final GLDrawable createExternalGLDrawableImpl() {
return WindowsExternalWGLDrawable.create(this, null);
}
@@ -553,25 +549,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return detail;
}
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
private static final int GAMMA_RAMP_LENGTH = 256;
+ @Override
protected final int getGammaRampLength() {
return GAMMA_RAMP_LENGTH;
}
+ @Override
protected final boolean setGammaRamp(float[] ramp) {
short[] rampData = new short[3 * GAMMA_RAMP_LENGTH];
for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) {
@@ -587,6 +576,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return res;
}
+ @Override
protected final Buffer getGammaRamp() {
ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]);
long screenDC = GDI.GetDC(0);
@@ -598,6 +588,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return rampData;
}
+ @Override
protected final void resetGammaRamp(Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
// getGammaRamp failed earlier
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDynamicLibraryBundleInfo.java
index a553bd4c2..6098cde7f 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,31 +20,31 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ *
* The views and conclusions contained in the software 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>();
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 5682b35e8..5dd9f88b2 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,26 +46,27 @@ 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 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.GLGraphicsConfigurationUtil;
-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,
+ WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen,
GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser) {
super(screen, capsChosen, capsRequested);
@@ -96,15 +99,15 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
AbstractGraphicsDevice device = screen.getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat();
WGLGLCapabilities caps = null;
if(hasARB) {
- caps = wglARBPFID2GLCapabilities(sharedResource, hdc, pfdID, glp, onscreen, true /* pbuffer */);
+ caps = wglARBPFID2GLCapabilities(sharedResource, device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS);
} else {
- caps = PFD2GLCapabilities(glp, hdc, pfdID, onscreen);
+ caps = PFD2GLCapabilities(device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS);
}
if(null==caps) {
throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+
@@ -116,6 +119,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return cfg;
}
+ @Override
public Object clone() {
return super.clone();
}
@@ -158,19 +162,19 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
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 +
+ 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);
+ bb.setDwFlags(GDI.DWM_BB_ENABLE| GDI.DWM_BB_TRANSITIONONMAXIMIZED);
+ bb.setFEnable( 1 );
boolean ok = GDI.DwmEnableBlurBehindWindow(hwnd, bb);
- if(ok) {
+ if( ok ) {
MARGINS m = MARGINS.create();
m.setCxLeftWidth(-1);
m.setCxRightWidth(-1);
@@ -179,15 +183,17 @@ 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) {
- System.err.println("setPixelFormat (ARB): hdc "+toHexString(hdc) +", "+caps);
+ System.err.println("setPixelFormat: hdc "+toHexString(hdc) +", "+caps);
}
setCapsPFD(caps);
}
-
+
/**
* Only sets this configuration's capabilities and marks it as determined,
* the actual pixelformat is not set.
@@ -204,130 +210,120 @@ 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(WindowsWGLDrawableFactory.SharedResource sharedResource, 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;
- }
-
- if(sharedResource.hasARBPBuffer()) {
- WindowsWGLContext sharedCtx = sharedResource.getContext();
- if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
- // pbo float buffer
- iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; // nvidia
- }
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLE_BUFFERS_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_SAMPLES_ARB);
}
-
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)) {
+ 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[] wglAllARBPFIDs(WindowsWGLContext sharedCtx, long hdc) {
- int[] iattributes = new int[1];
- int[] iresults = new int[1];
+ static int wglARBPFDIDCount(WindowsWGLContext sharedCtx, 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;
- if (!wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) {
+ // 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, iresults)) {
if(DEBUG) {
System.err.println("GetPixelFormatAttribivARB: Failed - HDC 0x" + Long.toHexString(hdc) +
+ ", value "+iresults.get(0)+
", LastError: " + GDI.GetLastError());
Thread.dumpStack();
}
- return null;
+ return 0;
}
- int numFormats = iresults[0];
- if(0 == numFormats) {
+ final int pfdIDCount = iresults.get(0);
+ if(0 == pfdIDCount) {
if(DEBUG) {
System.err.println("GetPixelFormatAttribivARB: No formats - HDC 0x" + Long.toHexString(hdc) +
", LastError: " + GDI.GetLastError());
Thread.dumpStack();
}
- return null;
}
- int[] pfdIDs = new int[numFormats];
- for (int i = 0; i < numFormats; i++) {
+ return pfdIDCount;
+ }
+
+ static int[] wglAllARBPFDIDs(int pfdIDCount) {
+ int[] pfdIDs = new int[pfdIDCount];
+ for (int i = 0; i < pfdIDCount; i++) {
pfdIDs[i] = 1 + i;
}
return pfdIDs;
}
static WGLGLCapabilities wglARBPFID2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
- long hdc, int pfdID,
- GLProfile glp, boolean onscreen, boolean usePBuffer) {
+ AbstractGraphicsDevice device, GLProfile glp,
+ long hdc, int pfdID, 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 (!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());
}
- ArrayList<WGLGLCapabilities> bucket = new ArrayList<WGLGLCapabilities>(1);
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- if(AttribList2GLCapabilities(bucket, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits)) {
- return bucket.get(0);
- }
- return null;
+ return AttribList2GLCapabilities(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits);
}
- static int[] wglChoosePixelFormatARB(long hdc, WindowsWGLDrawableFactory.SharedResource sharedResource,
+ static int[] wglChoosePixelFormatARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device,
GLCapabilitiesImmutable capabilities,
- int[] iattributes, int accelerationMode, float[] fattributes)
+ long hdc, IntBuffer iattributes, int accelerationMode, FloatBuffer fattributes)
{
if ( !WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities,
@@ -340,77 +336,83 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return null;
}
- int[] pformatsTmp = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS];
- int[] numFormatsTmp = new int[1];
- if ( !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, hdc, pformats[i],
- capabilities.getGLProfile(), capabilities.isOnscreen(), capabilities.isPBuffer());
+ 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,
- long hdc, int[] pfdIDs, GLProfile glp, boolean onscreen, boolean usePBuffer) {
- final int winattrbits = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, winattrbits);
- }
-
- static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2AllGLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
- long hdc, int[] pfdIDs, GLProfile glp) {
- return wglARBPFIDs2GLCapabilitiesImpl(sharedResource, hdc, pfdIDs, glp, GLGraphicsConfigurationUtil.ALL_BITS);
- }
-
- private static List /*<GLCapabilitiesImmutable>*/ wglARBPFIDs2GLCapabilitiesImpl(WindowsWGLDrawableFactory.SharedResource sharedResource,
- long hdc, int[] pfdIDs, GLProfile glp, int winattrbits) {
+ static List <GLCapabilitiesImmutable> wglARBPFIDs2GLCapabilities(WindowsWGLDrawableFactory.SharedResource sharedResource,
+ AbstractGraphicsDevice device, GLProfile glp, long hdc, int[] pfdIDs, int winattrbits, 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>();
for(int i = 0; i<numFormats; i++) {
if ( pfdIDs[i] >= 1 &&
- sharedResource.getContext().getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) {
- AttribList2GLCapabilities(bucket, 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;
+ 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);
+ System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> skip]: pfdID "+pfdIDs[i]+", "+skipped+", winattr "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString());
+ }
} else if (DEBUG) {
- System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " +
- i + "/" + numFormats + ": " + pfdIDs[i] + ", " +
- GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString());
+ if( 1 > pfdIDs[i] ) {
+ System.err.println("wglARBPFIDs2GLCapabilities: Invalid pfdID " + i + "/" + numFormats + ": " + pfdIDs[i]);
+ } else {
+ System.err.println("wglARBPFIDs2GLCapabilities: Cannot get pixel format attributes for pixel format " +
+ i + "/" + numFormats + ": " + pfdIDs[i] + ", hdc " + toHexString(hdc));
+ }
}
}
return bucket;
}
static boolean GLCapabilities2AttribList(GLCapabilitiesImmutable caps,
- int[] iattributes,
+ IntBuffer iattributes,
WindowsWGLDrawableFactory.SharedResource sharedResource,
int accelerationValue,
int[] floatMode) throws GLException {
@@ -418,212 +420,145 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return false;
}
- boolean onscreen = caps.isOnscreen();
- boolean pbuffer = caps.isPBuffer();
-
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;
- }
- if (onscreen) {
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
- } else if (pbuffer && sharedResource.hasARBPBuffer()) {
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
+ 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;
+ } else if( caps.isFBO() ) {
+ surfaceType = WGLExt.WGL_DRAW_TO_WINDOW_ARB; // native replacement!
+ } else if( usePBuffer ) {
+ surfaceType = WGLExt.WGL_DRAW_TO_PBUFFER_ARB;
+ } else if( caps.isBitmap() ) {
+ surfaceType = WGLExt.WGL_DRAW_TO_BITMAP_ARB;
} else {
- iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_BITMAP_ARB;
- iattributes[niattribs++] = GL.GL_TRUE;
+ throw new GLException("no surface type set in caps: "+caps);
}
+ iattributes.put(niattribs++, surfaceType);
+ iattributes.put(niattribs++, GL.GL_TRUE);
- iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB;
+ 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();
+ 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();
+ 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 (pbuffer && sharedResource.hasARBPBuffer()) {
- // 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");
- }
-
- WindowsWGLContext sharedCtx = sharedResource.getContext();
- if (rect) {
- if (!sharedCtx.isExtensionAvailable("GL_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) val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
+ 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) val |= GLGraphicsConfigurationUtil.BITMAP_BIT;
+ 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) val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
+ if(iresults.get(i) == GL.GL_TRUE) {
+ val |= GLGraphicsConfigurationUtil.PBUFFER_BIT;
+ }
break;
}
}
return val;
}
- static boolean AttribList2GLCapabilities( ArrayList<? extends GLCapabilitiesImmutable> capsBucket,
- final GLProfile glp, final long hdc, final int pfdID, final int[] iattribs,
- final int niattribs,
- final int[] iresults, final int winattrmask) {
+ static WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device,
+ final GLProfile glp, final long hdc, final int pfdID,
+ final IntBuffer iattribs, final int niattribs, IntBuffer iresults, final int winattrmask) {
final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults);
int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
- return false;
+ return null;
}
PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor();
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);
+ drawableTypeBits = drawableTypeBits & ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT | GLGraphicsConfigurationUtil.FBO_BIT );
if( 0 == drawableTypeBits ) {
- return false;
+ return null;
}
// non displayable requested (pbuffer)
}
- WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
+ final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
res.setValuesByARB(iattribs, niattribs, iresults);
-
- return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits );
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
}
//
@@ -649,7 +584,8 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
int dwFlags = pfd.getDwFlags();
if( 0 != (GDI.PFD_DRAW_TO_WINDOW & dwFlags ) ) {
- val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
+ val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
+ GLGraphicsConfigurationUtil.FBO_BIT;
}
if( 0 != (GDI.PFD_DRAW_TO_BITMAP & dwFlags ) ) {
val |= GLGraphicsConfigurationUtil.BITMAP_BIT;
@@ -657,107 +593,138 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
return val;
}
- static WGLGLCapabilities PFD2GLCapabilities(GLProfile glp, long hdc, int pfdID, boolean onscreen) {
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
- ArrayList<WGLGLCapabilities> capsBucket = new ArrayList<WGLGLCapabilities>(1);
- if( PFD2GLCapabilities(capsBucket, glp, hdc, pfdID, winattrmask) ) {
- return capsBucket.get(0);
- }
- return null;
- }
-
- static boolean PFD2GLCapabilities(ArrayList<? extends GLCapabilitiesImmutable> capsBucket, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) {
+ static WGLGLCapabilities PFD2GLCapabilities(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) {
PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
if(null == pfd) {
- return false;
+ return null;
}
- if ((pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
- return false;
+ if ( (pfd.getDwFlags() & GDI.PFD_SUPPORT_OPENGL) == 0) {
+ return null;
}
final int allDrawableTypeBits = PFD2DrawableTypeBits(pfd);
final int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
- return false;
+ 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;
+ }
}
- WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
+ final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
res.setValuesByGDI();
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
+ }
- return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits );
- }
+ static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID) {
+ PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID);
+ return PFD2GLCapabilitiesNoCheck(device, glp, pfd, pfdID);
+ }
- static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) {
- 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 pfdFlags = (GDI.PFD_SUPPORT_OPENGL |
- GDI.PFD_GENERIC_ACCELERATED);
- if (caps.getDoubleBuffered()) {
- pfdFlags |= GDI.PFD_DOUBLEBUFFER;
- }
- if (caps.isOnscreen()) {
- pfdFlags |= GDI.PFD_DRAW_TO_WINDOW;
- } else {
- pfdFlags |= GDI.PFD_DRAW_TO_BITMAP;
- }
- if (caps.getStereo()) {
- pfdFlags |= GDI.PFD_STEREO;
- }
- pfd.setDwFlags(pfdFlags);
- pfd.setIPixelType((byte) GDI.PFD_TYPE_RGBA);
- pfd.setCColorBits((byte) colorDepth);
- pfd.setCRedBits ((byte) caps.getRedBits());
- pfd.setCGreenBits((byte) caps.getGreenBits());
- pfd.setCBlueBits ((byte) caps.getBlueBits());
- pfd.setCAlphaBits((byte) caps.getAlphaBits());
- int accumDepth = (caps.getAccumRedBits() +
- caps.getAccumGreenBits() +
- caps.getAccumBlueBits());
- pfd.setCAccumBits ((byte) accumDepth);
- pfd.setCAccumRedBits ((byte) caps.getAccumRedBits());
- pfd.setCAccumGreenBits((byte) caps.getAccumGreenBits());
- pfd.setCAccumBlueBits ((byte) caps.getAccumBlueBits());
- pfd.setCAccumAlphaBits((byte) caps.getAccumAlphaBits());
- pfd.setCDepthBits((byte) caps.getDepthBits());
- pfd.setCStencilBits((byte) caps.getStencilBits());
- pfd.setILayerType((byte) GDI.PFD_MAIN_PLANE);
-
- // n/a with non ARB/GDI method:
- // multisample
- // opaque
- // pbuffer
- return pfd;
- }
-
- static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) {
- PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create();
- pfd.setNSize((short) PIXELFORMATDESCRIPTOR.size());
- pfd.setNVersion((short) 1);
- if(0 != hdc && 1 <= pfdID) {
- if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) {
- // Accelerated pixel formats that are non displayable
- if(DEBUG) {
- System.err.println("Info: Non displayable pixel format " + pfdID + " of device context: error code " + GDI.GetLastError());
- }
+ static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) {
+ if(null == pfd) {
return null;
}
- }
- return pfd;
- }
-
- static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() {
- return createPixelFormatDescriptor(0, 0);
- }
-
- public String toString() {
- return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + getPixelFormatID() + ", ARB-Choosen " + isChoosenByARB() +
- ",\n\trequested " + getRequestedCapabilities() +
- ",\n\tchosen " + getChosenCapabilities() +
- "]";
- }
+ final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp);
+ res.setValuesByGDI();
+
+ return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res);
+ }
+
+ static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) {
+ 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 pfdFlags = ( GDI.PFD_SUPPORT_OPENGL | GDI.PFD_GENERIC_ACCELERATED );
+
+ if( caps.isOnscreen() ) {
+ pfdFlags |= GDI.PFD_DRAW_TO_WINDOW;
+ } else if( caps.isFBO() ) {
+ pfdFlags |= GDI.PFD_DRAW_TO_WINDOW; // native replacement!
+ } else if( caps.isPBuffer() ) {
+ pfdFlags |= GDI.PFD_DRAW_TO_BITMAP; // pbuffer n/a, use bitmap
+ } else if( caps.isBitmap() ) {
+ pfdFlags |= GDI.PFD_DRAW_TO_BITMAP;
+ } else {
+ throw new GLException("no surface type set in caps: "+caps);
+ }
+
+ if ( caps.getDoubleBuffered() ) {
+ if( caps.isBitmap() || caps.isPBuffer() ) {
+ pfdFlags |= GDI.PFD_DOUBLEBUFFER_DONTCARE; // bitmaps probably don't have dbl buffering
+ } else {
+ pfdFlags |= GDI.PFD_DOUBLEBUFFER;
+ }
+ }
+
+ if (caps.getStereo()) {
+ pfdFlags |= GDI.PFD_STEREO;
+ }
+ pfd.setDwFlags(pfdFlags);
+ pfd.setIPixelType((byte) GDI.PFD_TYPE_RGBA);
+ pfd.setCColorBits((byte) colorDepth);
+ pfd.setCRedBits ((byte) caps.getRedBits());
+ pfd.setCGreenBits((byte) caps.getGreenBits());
+ pfd.setCBlueBits ((byte) caps.getBlueBits());
+ pfd.setCAlphaBits((byte) caps.getAlphaBits());
+ int accumDepth = (caps.getAccumRedBits() +
+ caps.getAccumGreenBits() +
+ caps.getAccumBlueBits());
+ pfd.setCAccumBits ((byte) accumDepth);
+ pfd.setCAccumRedBits ((byte) caps.getAccumRedBits());
+ pfd.setCAccumGreenBits((byte) caps.getAccumGreenBits());
+ pfd.setCAccumBlueBits ((byte) caps.getAccumBlueBits());
+ pfd.setCAccumAlphaBits((byte) caps.getAccumAlphaBits());
+ pfd.setCDepthBits((byte) caps.getDepthBits());
+ pfd.setCStencilBits((byte) caps.getStencilBits());
+ pfd.setILayerType((byte) GDI.PFD_MAIN_PLANE);
+
+ // n/a with non ARB/GDI method:
+ // multisample
+ // opaque
+ // pbuffer
+ return pfd;
+ }
+
+ static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor(long hdc, int pfdID) {
+ PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create();
+ pfd.setNSize((short) PIXELFORMATDESCRIPTOR.size());
+ pfd.setNVersion((short) 1);
+ if(0 != hdc && 1 <= pfdID) {
+ if (WGLUtil.DescribePixelFormat(hdc, pfdID, PIXELFORMATDESCRIPTOR.size(), pfd) == 0) {
+ // Accelerated pixel formats that are non displayable
+ if(DEBUG) {
+ System.err.println("Info: Non displayable pixel format " + pfdID + " of device context: error code " + GDI.GetLastError());
+ }
+ return null;
+ }
+ }
+ return pfd;
+ }
+
+ static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() {
+ return createPixelFormatDescriptor(0, 0);
+ }
+
+ @Override
+ public String toString() {
+ return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + getPixelFormatID() + ", ARB-Choosen " + isChoosenByARB() +
+ ",\n\trequested " + getRequestedCapabilities() +
+ ",\n\tchosen " + getChosenCapabilities() +
+ "]";
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index 2c8c03185..969e45ed8 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,11 +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;
@@ -68,13 +74,14 @@ 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, 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) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
@@ -84,7 +91,11 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - requested");
}
- return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, chooser, absScreen);
+ if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
+ throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
+ }
+
+ return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen);
}
static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLCapabilitiesImmutable caps,
@@ -94,34 +105,34 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
- CapabilitiesChooser chooser,
+ GLCapabilitiesChooser chooser,
AbstractGraphicsScreen absScreen) {
if(null==absScreen) {
absScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_WINDOWS);
}
- AbstractGraphicsDevice absDevice = absScreen.getDevice();
-
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities(
- capsChosen, GLDrawableFactory.getDesktopFactory().canCreateGLPbuffer(absDevice) );
-
- return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, (GLCapabilitiesChooser)chooser );
+ final AbstractGraphicsDevice absDevice = absScreen.getDevice();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getDesktopFactory(), absDevice);
+ return new WindowsWGLGraphicsConfiguration( absScreen, capsChosen, capsReq, chooser );
}
protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) {
- WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
- WindowsWGLDrawable sharedDrawable = sharedResource.getDrawable();
- GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities();
- WindowsWGLContext sharedContext = sharedResource.getContext();
- List/*<GLCapabilitiesImmutable>*/ availableCaps = null;
-
- if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+ final GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
+ final GLProfile glp = GLProfile.getDefault(device);
+
+ List<GLCapabilitiesImmutable> availableCaps = null;
+
+ 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 {
@@ -130,17 +141,21 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
throw new GLException("Error: HDC is null");
}
if (sharedResource.hasARBPixelFormat()) {
- availableCaps = getAvailableGLCapabilitiesARB(hdc, sharedResource, capsChosen.getGLProfile());
+ availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc);
}
- if( null == availableCaps || availableCaps.isEmpty() ) {
- availableCaps = getAvailableGLCapabilitiesGDI(hdc, capsChosen.getGLProfile());
+ 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 ) {
@@ -149,17 +164,23 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return availableCaps;
}
- static List/*<GLCapabilitiesImmutable>*/ getAvailableGLCapabilitiesARB(long hdc, WindowsWGLDrawableFactory.SharedResource sharedResource, GLProfile glProfile) {
- int[] pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
- return WindowsWGLGraphicsConfiguration.wglARBPFIDs2AllGLCapabilities(sharedResource, hdc, pformats, glProfile);
+ private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, GLProfile glProfile, 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 & ~GLGraphicsConfigurationUtil.BITMAP_BIT, false); // w/o BITMAP
}
- static List/*<GLCapabilitiesImmutable>*/ getAvailableGLCapabilitiesGDI(long hdc, GLProfile glProfile) {
+ private static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesGDI(AbstractGraphicsDevice device, GLProfile glProfile, long hdc, boolean bitmapOnly) {
int[] pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
int numFormats = pformats.length;
- ArrayList<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(numFormats);
+ List<GLCapabilitiesImmutable> bucket = new ArrayList<GLCapabilitiesImmutable>(numFormats);
for (int i = 0; i < numFormats; i++) {
- WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(bucket, 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);
+ }
}
return bucket;
}
@@ -206,7 +227,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);
@@ -264,17 +285,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);
- WindowsWGLContext sharedContext = null;
- if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
+ 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(hdc, extHDC, config, chooser, (WindowsWGLDrawableFactory)factory, pfdIDs) ) {
- updateGraphicsConfigurationGDI(hdc, extHDC, config, chooser, 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 {
if (null != sharedContext) {
@@ -283,10 +311,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
}
- private static boolean updateGraphicsConfigurationARB(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config,
- CapabilitiesChooser chooser, WindowsWGLDrawableFactory factory, int[] pformats) {
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ private static boolean updateGraphicsConfigurationARB(WindowsWGLDrawableFactory factory, WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser,
+ long hdc, boolean extHDC, int[] pformats) {
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if (null == sharedResource) {
if (DEBUG) {
@@ -301,14 +329,25 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return false;
}
- GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- boolean isOpaque = capsChosen.isBackgroundOpaque() && GDI.DwmIsCompositionEnabled();
- boolean onscreen = capsChosen.isOnscreen();
- boolean usePBuffer = capsChosen.isPBuffer();
- GLProfile glProfile = capsChosen.getGLProfile();
-
+ final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final boolean isOpaque = capsChosen.isBackgroundOpaque() && GDI.DwmIsCompositionEnabled();
+ 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("translucency requested: "+(!capsChosen.isBackgroundOpaque())+", compositioning enabled: "+GDI.DwmIsCompositionEnabled()+" -> translucency "+(!isOpaque));
+ System.err.println("updateGraphicsConfigurationARB: hdc "+toHexString(hdc)+", pfdIDCount(hdc) "+pfdIDCount+", capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString());
+ 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) {
+ if (DEBUG) {
+ System.err.println("updateGraphicsConfigurationARB: failed due to 0 pfdIDs for hdc "+toHexString(hdc)+" - hdc incompatible w/ ARB ext.");
+ }
+ return false;
}
WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps
@@ -324,29 +363,28 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
+ ", pixelformat " + presetPFDID);
}
pixelFormatSet = true;
- pixelFormatCaps = WindowsWGLGraphicsConfiguration.wglARBPFID2GLCapabilities(sharedResource, hdc, presetPFDID, glProfile, onscreen, usePBuffer);
+ 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(hdc, sharedResource, capsChosen,
- iattributes, accelerationMode, fattributes);
+ pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(sharedResource, device, capsChosen,
+ hdc, iattributes, accelerationMode, fattributes);
if (null == pformats) {
accelerationMode = WGLExt.WGL_GENERIC_ACCELERATION_ARB;
- pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedResource, capsChosen,
- iattributes, accelerationMode, fattributes);
+ pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(sharedResource, device, capsChosen,
+ hdc, iattributes, accelerationMode, fattributes);
}
if (null == pformats) {
accelerationMode = -1; // use what we are offered ..
- pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(hdc, sharedResource, capsChosen,
- iattributes, accelerationMode, fattributes);
+ pformats = WindowsWGLGraphicsConfiguration.wglChoosePixelFormatARB(sharedResource, device, capsChosen,
+ hdc, iattributes, accelerationMode, fattributes);
}
if (null != pformats) {
recommendedIndex = 0;
@@ -355,7 +393,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
System.err.println("updateGraphicsConfigurationARB: wglChoosePixelFormatARB failed with: "+capsChosen);
}
// 2nd choice: get all GLCapabilities available, no preferred recommendedIndex available
- pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFIDs(sharedResource.getContext(), hdc);
+ pformats = WindowsWGLGraphicsConfiguration.wglAllARBPFDIDs(pfdIDCount);
if (DEBUG) {
final int len = ( null != pformats ) ? pformats.length : 0;
System.err.println("updateGraphicsConfigurationARB: NumFormats (wglAllARBPFIDs) " + len);
@@ -369,14 +407,14 @@ 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 /*<WGLGLCapabilities>*/ availableCaps =
- WindowsWGLGraphicsConfiguration.wglARBPFIDs2GLCapabilities(sharedResource, hdc, pformats,
- glProfile, onscreen, usePBuffer);
if( null == availableCaps || 0 == availableCaps.size() ) {
if (DEBUG) {
- System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length +
- " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer);
+ System.err.println("updateGraphicsConfigurationARB: wglARBPFIDs2GLCapabilities failed with " + pformats.length + " pfd ids");
Thread.dumpStack();
}
return false;
@@ -384,14 +422,19 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
if (DEBUG) {
System.err.println("updateGraphicsConfigurationARB: " + pformats.length +
- " pfd ids, onscreen " + onscreen + ", pbuffer " + usePBuffer + ", " + 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();
@@ -402,12 +445,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);
}
}
@@ -419,61 +462,121 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
return true;
}
- private static boolean updateGraphicsConfigurationGDI(long hdc, boolean extHDC, WindowsWGLGraphicsConfiguration config,
- CapabilitiesChooser chooser, int[] pformats) {
- GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- if(capsChosen.isPBuffer()) {
+ private static boolean updateGraphicsConfigurationGDI(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, long hdc,
+ 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);
}
return false;
}
- boolean onscreen = capsChosen.isOnscreen();
- GLProfile glProfile = capsChosen.getGLProfile();
+ // final boolean onscreen = capsChosen.isOnscreen();
+ // final boolean useFBO = capsChosen.isFBO();
+ final GLProfile glProfile = capsChosen.getGLProfile();
+ final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen);
+
+ if(DEBUG) {
+ 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);
+ }
- ArrayList<WGLGLCapabilities> availableCaps = new ArrayList<WGLGLCapabilities>();
- 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(glProfile, hdc, pfdID, onscreen);
+ pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, presetPFDID, winattrmask);
+ if(null == pixelFormatCaps) {
+ throw new GLException("Could not map PFD2GLCaps w/ already chosen pfdID "+presetPFDID);
+ }
} else {
- if(null == pformats) {
+ final boolean givenPFormats = null != pformats;
+ if( !givenPFormats ) {
pformats = WindowsWGLGraphicsConfiguration.wglAllGDIPFIDs(hdc);
}
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, false);
-
- for (int i = 0; i < pformats.length; i++) {
- WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(availableCaps, glProfile, hdc, pformats[i], winattrmask);
- }
// 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 ) {
- // seek index ..
- for (recommendedIndex = availableCaps.size() - 1 ;
- 0 <= recommendedIndex && pfdID != ((WGLGLCapabilities) availableCaps.get(recommendedIndex)).getPFDID();
- recommendedIndex--)
- { /* nop */ }
+ final boolean skipCapsChooser;
+ if( 1 <= chosenPFDID ) {
+ final boolean _skipCapsChooser = null == chooser && capsChosen.isBackgroundOpaque(); // fast path: skip choosing if using recommended idx and null chooser is used and if not translucent
+ // seek index .. in all formats _or_ in given formats!
+ 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);
+ availableCaps.add(caps);
+ recommendedIndex = 0;
+ skipCapsChooser = true;
+ } 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;
}
- // 2nd choice: if no preferred recommendedIndex available
if (DEBUG) {
- System.err.println("updateGraphicsConfigurationGDI: ChoosePixelFormat(HDC " + toHexString(hdc) + ") = " + 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) {
+ 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
+ final int chosenIndex;
+ if( skipCapsChooser ) {
+ chosenIndex = recommendedIndex;
+ } else {
+ chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
}
- int chosenIndex = chooseCapabilities(chooser, capsChosen, availableCaps, recommendedIndex);
if ( 0 > chosenIndex ) {
if (DEBUG) {
System.err.println("updateGraphicsConfigurationGDI: failed, return false");
@@ -481,10 +584,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
return false;
}
- pixelFormatCaps = availableCaps.get(chosenIndex);
+ pixelFormatCaps = (WGLGLCapabilities) availableCaps.get(chosenIndex);
if (DEBUG) {
- System.err.println("chosen pfdID (GDI): native recommended "+ (recommendedIndex+1) +
- ", caps " + pixelFormatCaps);
+ System.err.println("chosen pfdID (GDI): recommendedIndex "+recommendedIndex+" -> chosenIndex "+ chosenIndex + ", skipCapsChooser "+skipCapsChooser+", caps " + pixelFormatCaps +
+ " (" + WGLGLCapabilities.PFD2String(pixelFormatCaps.getPFD(), pixelFormatCaps.getPFDID()) +")");
}
}
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 bd64b58a4..96bd0bdd0 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
@@ -63,14 +63,15 @@ import javax.media.opengl.GLDrawableFactory;
public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
public static void registerFactory() {
- GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.awt.AWTGraphicsDevice.class, new WindowsAWTWGLGraphicsConfigurationFactory());
+ 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) {
+ CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
GraphicsDevice device = null;
if (absScreen != null &&
!(absScreen instanceof AWTGraphicsScreen)) {
@@ -105,16 +106,16 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex());
- GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice);
+ GraphicsConfigurationFactory configFactory = GraphicsConfigurationFactory.getFactory(winDevice, capsChosen);
WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration)
configFactory.chooseGraphicsConfiguration(capsChosen,
capsRequested,
- chooser, winScreen);
+ chooser, winScreen, nativeVisualID);
if (winConfig == null) {
throw new GLException("Unable to choose a GraphicsConfiguration: "+capsChosen+",\n\t"+chooser+"\n\t"+winScreen);
}
- GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(((GLCapabilitiesImmutable)capsChosen).getGLProfile());
+ GLDrawableFactory drawableFactory = GLDrawableFactory.getFactory(((GLCapabilitiesImmutable)capsChosen).getGLProfile());
GraphicsConfiguration chosenGC = null;
if ( drawableFactory instanceof WindowsWGLDrawableFactory ) {
@@ -138,7 +139,7 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
}
// go on ..
}
-
+
if( null == chosenGC ) {
// 2nd Choice: Choose and match the GL Visual with AWT:
// - collect all AWT PFDs
@@ -147,7 +148,7 @@ 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];
@@ -171,11 +172,11 @@ public class WindowsAWTWGLGraphicsConfigurationFactory extends GLGraphicsConfigu
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..12e3db3bd 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,54 +33,91 @@
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) {
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, 0, null, 0);
- } catch (Throwable t) { /* n/a */ }
- return glXAvailable;
+ glXAvailable = GLX.glXQueryExtension(x11Device.getHandle(), null, null);
+ } catch (Throwable t) { /* n/a */
+ } finally {
+ x11Device.unlock();
+ }
+ return glXAvailable;
}
-
- 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 getGLXClientString(X11GraphicsDevice x11Device, int name) {
+ x11Device.lock();
+ try {
+ return GLX.glXGetClientString(x11Device.getHandle(), name);
+ } finally {
+ x11Device.unlock();
+ }
+ }
+ public static String queryGLXServerString(X11GraphicsDevice x11Device, int screen_idx, int name) {
+ x11Device.lock();
+ try {
+ return GLX.glXQueryServerString(x11Device.getHandle(), screen_idx, name);
+ } finally {
+ x11Device.unlock();
+ }
+ }
+ public static String queryGLXExtensionsString(X11GraphicsDevice x11Device, 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(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) {
+ String str = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VERSION);
+ try {
+ // e.g. "1.3"
+ major.put(0, Integer.valueOf(str.substring(0, 1)).intValue());
+ minor.put(0, Integer.valueOf(str.substring(2, 3)).intValue());
+ } catch (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) {
if (extensions != null) {
return (extensions.indexOf("GLX_ARB_multisample") >= 0);
@@ -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(X11GraphicsDevice x11Device) {
if(null != clientVendorName) {
return; // already initialized
}
@@ -115,10 +152,10 @@ 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 String str = GLX.glXGetClientString(x11Device.getHandle(), GLX.GLX_VERSION);
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java
deleted file mode 100644
index a1039e552..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.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.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-import com.jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import com.jogamp.nativewindow.x11.X11GraphicsScreen;
-
-import jogamp.nativewindow.*;
-import jogamp.nativewindow.x11.*;
-
-public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable {
- private static final int f_dim = 64;
- private long dummyWindow = 0;
-
- /**
- * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
- * we cannot switch the Display as we please,
- * hence we reuse the target's screen configuration.
- */
- public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLCapabilitiesImmutable caps) {
- super(factory,
- new WrappedSurface(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(
- caps, caps, null, screen)));
- this.realized = true;
-
- WrappedSurface ns = (WrappedSurface) getNativeSurface();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)ns.getGraphicsConfiguration();
-
- X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
- long dpy = device.getHandle();
- int scrn = screen.getIndex();
- int visualID = config.getXVisualID();
-
- dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID, f_dim, f_dim);
- ns.setSurfaceHandle( dummyWindow );
- ns.surfaceSizeChanged(f_dim, f_dim);
-
- updateHandle();
- }
-
- public static X11DummyGLXDrawable create(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) {
- GLCapabilities caps = new GLCapabilities(glp);
- return new X11DummyGLXDrawable(screen, factory, caps);
- }
-
- public void setSize(int width, int height) {
- }
-
- public int getWidth() {
- return 1;
- }
-
- public int getHeight() {
- return 1;
- }
-
- protected void destroyImpl() {
- if(0!=dummyWindow) {
- destroyHandle();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
- X11Lib.DestroyDummyWindow(config.getScreen().getDevice().getHandle(), dummyWindow);
- }
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index 700b25662..ff9363ca0 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.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,38 +29,42 @@
* 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 java.nio.IntBuffer;
+
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import jogamp.opengl.GLContextImpl;
+import jogamp.nativewindow.WrappedSurface;
import jogamp.opengl.GLContextShareSet;
-import com.jogamp.nativewindow.WrappedSurface;
+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) {
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
}
@@ -77,58 +81,51 @@ public class X11ExternalGLXContext extends X11GLXContext {
if (drawable == 0) {
throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current");
}
- int[] val = new int[1];
- GLX.glXQueryContext(display, ctx, GLX.GLX_SCREEN, val, 0);
- X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0], false);
+ IntBuffer val = Buffers.newDirectIntBuffer(1);
+
+ int w, h;
+ 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);
+ X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val.get(0), false);
- GLX.glXQueryContext(display, ctx, GLX.GLX_FBCONFIG_ID, val, 0);
+ 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( X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val[0]) ) {
+ if( VisualIDHolder.VID_UNDEFINED == val.get(0) || !X11GLXGraphicsConfiguration.GLXFBConfigIDValid(display, x11Screen.getIndex(), val.get(0)) ) {
GLCapabilities glcapsDefault = new GLCapabilities(GLProfile.getDefault());
- cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(glcapsDefault, glcapsDefault, null, x11Screen);
+ 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));
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
+ final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, true);
return new X11ExternalGLXContext(new Drawable(factory, ns), ctx);
}
- protected boolean createImpl(GLContextImpl shareWith) {
+ @Override
+ protected boolean createImpl(final long shareWithHandle) {
return true;
}
- 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();
- }
-
- public void release() throws GLException {
- super.release();
- setCurrent(lastContext);
- lastContext = null;
- }
-
+ @Override
protected void makeCurrentImpl() throws GLException {
}
+ @Override
protected void releaseImpl() throws GLException {
}
+ @Override
protected void destroyImpl() throws GLException {
}
@@ -138,14 +135,17 @@ public class X11ExternalGLXContext extends X11GLXContext {
super(factory, comp, true);
}
+ @Override
public GLContext createContext(GLContext shareWith) {
throw new GLException("Should not call this");
}
+ @Override
public int getWidth() {
throw new GLException("Should not call this");
}
+ @Override
public int getHeight() {
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 4d0276163..650fd31d3 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.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,25 +28,28 @@
* 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 java.nio.IntBuffer;
+
import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
+import jogamp.nativewindow.WrappedSurface;
-import com.jogamp.nativewindow.WrappedSurface;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
@@ -69,31 +72,30 @@ public class X11ExternalGLXDrawable extends X11GLXDrawable {
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);
+ IntBuffer val = Buffers.newDirectIntBuffer(1);
+
+ GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val);
+ 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);
+ 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))+")");
}
}
- WrappedSurface ns = new WrappedSurface(cfg);
- ns.setSurfaceHandle(drawable);
- ns.surfaceSizeChanged(w, h);
- return new X11ExternalGLXDrawable(factory, ns);
+ return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, true));
}
+ @Override
public GLContext createContext(GLContext shareWith) {
return new Context(this, shareWith);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
index 96d4c7713..e0b69ffd4 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLCapabilities.java
@@ -55,10 +55,12 @@ public class X11GLCapabilities extends GLCapabilities {
this.fbcfgid = VisualIDHolder.VID_UNDEFINED;
}
+ @Override
public Object cloneMutable() {
return clone();
}
+ @Override
public Object clone() {
try {
return super.clone();
@@ -86,9 +88,10 @@ public class X11GLCapabilities extends GLCapabilities {
return getFBConfigID();
default:
throw new NativeWindowException("Invalid type <"+type+">");
- }
+ }
}
-
+
+ @Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
sink = new StringBuilder();
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 2fd8cbcd9..94620c4fc 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.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.
*/
@@ -57,25 +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>();
@@ -83,25 +90,28 @@ public abstract class X11GLXContext extends GLContextImpl {
functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV");
extensionNameMap = new HashMap<String, String>();
- extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer");
- extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough
+ extensionNameMap.put(GLExtensions.ARB_pbuffer, X11GLXDrawableFactory.GLX_SGIX_pbuffer);
+ extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough
}
X11GLXContext(GLDrawableImpl drawable,
GLContext shareWith) {
super(drawable, shareWith);
}
-
+
@Override
- protected void resetStates() {
+ protected void resetStates(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
public final ProcAddressTable getPlatformExtProcAddressTable() {
return getGLXExtProcAddressTable();
}
@@ -110,6 +120,7 @@ public abstract class X11GLXContext extends GLContextImpl {
return glXExtProcAddressTable;
}
+ @Override
public Object getPlatformGLExtensions() {
return getGLXExt();
}
@@ -121,14 +132,29 @@ public abstract class X11GLXContext extends GLContextImpl {
return _glXExt;
}
+ @Override
protected Map<String, String> getFunctionNameMap() { return functionNameMap; }
+ @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
public final boolean isGLReadDrawableAvailable() {
return isGLXVersionGreaterEqualOneThree();
}
@@ -138,15 +164,17 @@ public abstract class X11GLXContext extends GLContextImpl {
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(TRACE_SWITCH) {
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
@@ -158,14 +186,13 @@ public abstract class X11GLXContext extends GLContextImpl {
return res;
}
+ @Override
protected void destroyContextARBImpl(long ctx) {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
- long display = config.getScreen().getDevice().getHandle();
+ 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;
@@ -178,7 +205,8 @@ public abstract class X11GLXContext extends GLContextImpl {
/* 8 */ 0, 0,
/* 10 */ 0
};
-
+
+ @Override
protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) {
updateGLXProcAddressTable();
GLXExt _glXExt = getGLXExt();
@@ -197,15 +225,15 @@ public abstract class X11GLXContext extends GLContextImpl {
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);
-
+
if ( major > 3 || major == 3 && minor >= 2 ) {
attribs.put(ctx_arb_attribs_idx_profile + 0, GLX.GLX_CONTEXT_PROFILE_MASK_ARB);
if( ctBwdCompat ) {
attribs.put(ctx_arb_attribs_idx_profile + 1, GLX.GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
} else {
attribs.put(ctx_arb_attribs_idx_profile + 1, GLX.GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
- }
- }
+ }
+ }
if ( major >= 3 ) {
int flags = attribs.get(ctx_arb_attribs_idx_flags + 1);
@@ -220,20 +248,21 @@ public abstract class X11GLXContext extends GLContextImpl {
X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
AbstractGraphicsDevice device = config.getScreen().getDevice();
- long display = device.getHandle();
+ 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) {
if(DEBUG) {
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) {
@@ -253,54 +282,43 @@ public abstract class X11GLXContext extends GLContextImpl {
return ctx;
}
- 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) {
+ @Override
+ protected boolean createImpl(final long shareWithHandle) {
boolean direct = true; // try direct always
isDirect = false; // fall back
- X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl();
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsDevice device = config.getScreen().getDevice();
- X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device);
+ final X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContext(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);
+ 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( !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");
}
- 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 */, false /* 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;
}
@@ -308,63 +326,64 @@ 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)) {
+ 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 */, false /* 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 ) {
// 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+
+ System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+
", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable);
}
}
+ } 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()) {
+ 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()+", ");
+ throw new GLException(getThreadName()+": X11GLXContext.createContextImpl ctx !ARB, 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());
@@ -372,53 +391,53 @@ public abstract class X11GLXContext extends GLContextImpl {
// continue with temp context for GL <= 3.0
contextHandle = temp_ctx;
- if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
+ 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);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextImpl: OK direct "+isDirect+"/"+direct);
}
+
return true;
}
+ @Override
protected void makeCurrentImpl() throws GLException {
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);
+ 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();
@@ -430,6 +449,7 @@ public abstract class X11GLXContext extends GLContextImpl {
// Should check for X errors and raise GLException
}
+ @Override
protected final void updateGLXProcAddressTable() {
final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
@@ -458,65 +478,78 @@ 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();
+ 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;
}
- public boolean isExtensionAvailable(String glExtensionName) {
- if (glExtensionName.equals("GL_ARB_pbuffer") ||
- glExtensionName.equals("GL_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; }
+ 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 (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 (Throwable t) { hasSwapInterval=-1; }
}
return false;
}
@@ -524,15 +557,15 @@ public abstract class X11GLXContext extends GLContextImpl {
private final int initSwapGroupImpl(GLXExt glXExt) {
if(0==hasSwapGroupNV) {
try {
- hasSwapGroupNV = glXExt.isExtensionAvailable("GLX_NV_swap_group")?1:-1;
+ hasSwapGroupNV = glXExt.isExtensionAvailable(GLXExtensions.GLX_NV_swap_group)?1:-1;
} catch (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) {
@@ -541,16 +574,20 @@ public abstract class X11GLXContext extends GLContextImpl {
if (initSwapGroupImpl(glXExt)>0) {
final NativeSurface ns = drawable.getNativeSurface();
try {
- if( glXExt.glXQueryMaxSwapGroupsNV(ns.getDisplayHandle(), ns.getScreenIndex(),
- 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( glXExt.glXQueryMaxSwapGroupsNV(ns.getDisplayHandle(), ns.getScreenIndex(),
+ maxGroupsNIO, maxBarriersNIO) ) {
+ maxGroupsNIO.get(maxGroups, maxGroups_offset, maxGroupsNIO.remaining());
+ maxBarriersNIO.get(maxGroups, maxGroups_offset, maxBarriersNIO.remaining());
res = true;
}
} catch (Throwable t) { hasSwapGroupNV=-1; }
}
return res;
}
-
+
@Override
protected final boolean joinSwapGroupImpl(int group) {
boolean res = false;
@@ -565,7 +602,7 @@ public abstract class X11GLXContext extends GLContextImpl {
}
return res;
}
-
+
@Override
protected final boolean bindSwapBarrierImpl(int group, int barrier) {
boolean res = false;
@@ -577,34 +614,20 @@ public abstract class X11GLXContext extends GLContextImpl {
}
} catch (Throwable t) { hasSwapGroupNV=-1; }
}
- return res;
+ return res;
}
@Override
- public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
- return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3);
+ public final ByteBuffer glAllocateMemoryNV(int size, float readFrequency, float writeFrequency, float priority) {
+ return getGLXExt().glXAllocateMemoryNV(size, readFrequency, writeFrequency, priority);
}
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
+ @Override
+ public final void glFreeMemoryNV(ByteBuffer pointer) {
+ getGLXExt().glXFreeMemoryNV(pointer);
}
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
index 61f2ef9c9..155c00c4c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.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,45 +29,50 @@
* 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.nativewindow.*;
-import javax.media.opengl.*;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLDrawableFactory;
-import jogamp.opengl.*;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
public abstract class X11GLXDrawable extends GLDrawableImpl {
protected X11GLXDrawable(GLDrawableFactory factory, NativeSurface comp, boolean realized) {
super(factory, comp, realized);
}
+ @Override
public GLDynamicLookupHelper getGLDynamicLookupHelper() {
return getFactoryImpl().getGLDynamicLookupHelper(0);
}
+ @Override
protected void setRealizedImpl() {
if(realized) {
X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
config.updateGraphicsConfiguration();
if (DEBUG) {
- System.err.println("X11GLXDrawable.setRealized(true): "+config);
+ System.err.println(getThreadName()+": X11GLXDrawable.setRealized(true): "+config);
}
}
}
- protected final void swapBuffersImpl() {
- // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers()
- GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle());
+ @Override
+ protected final void swapBuffersImpl(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 092d3439e..f7938f463 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.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.
@@ -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,16 +49,19 @@ 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;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
-import javax.media.opengl.GLProfile.ShutdownType;
+import jogamp.nativewindow.WrappedSurface;
+import jogamp.nativewindow.x11.X11DummyUpstreamSurfaceHook;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
@@ -64,60 +69,78 @@ 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.util.VersionNumber;
-import com.jogamp.nativewindow.WrappedSurface;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
-
+
public static final VersionNumber versionOneZero = new VersionNumber(1, 0, 0);
public static final VersionNumber versionOneOne = new VersionNumber(1, 1, 0);
public static final VersionNumber versionOneTwo = new VersionNumber(1, 2, 0);
public static final VersionNumber versionOneThree = new VersionNumber(1, 3, 0);
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 (Exception ex) {
+ tmp = null;
+ if(DEBUG) {
+ ex.printStackTrace();
+ }
+ }
+ return tmp;
}
- }
- if(null!=tmp && tmp.isLibComplete()) {
- x11GLXDynamicLookupHelper = tmp;
- GLX.getGLXProcAddressTable().reset(x11GLXDynamicLookupHelper);
- }
+ } );
}
}
-
+
defaultDevice = new X11GraphicsDevice(X11Util.getNullDisplayName(), AbstractGraphicsDevice.DEFAULT_UNIT);
-
+
if(null!=x11GLXDynamicLookupHelper) {
// Register our GraphicsConfigurationFactory implementations
// The act of constructing them causes them to be registered
X11GLXGraphicsConfigurationFactory.registerFactory();
-
+
sharedMap = new HashMap<String, SharedResourceRunner.Resource>();
-
+
// Init shared resources off thread
// Will be released via ShutdownHook
sharedResourceRunner = new SharedResourceRunner(new SharedResourceImplementation());
sharedResourceRunner.start();
- }
+ }
+ }
+
+ @Override
+ protected final boolean isComplete() {
+ return null != x11GLXDynamicLookupHelper;
}
- protected final void destroy(ShutdownType shutdownType) {
+ @Override
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("X11GLXDrawableFactory.shutdown");
+ }
if(null != sharedResourceRunner) {
sharedResourceRunner.stop();
sharedResourceRunner = null;
@@ -129,57 +152,65 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
defaultDevice = null;
/**
* Pulling away the native library may cause havoc ..
- *
- if(ShutdownType.COMPLETE == shutdownType && null != x11GLXDynamicLookupHelper) {
- x11GLXDynamicLookupHelper.destroy();
- x11GLXDynamicLookupHelper = null;
- } */
-
- // Don't really close pending Display connections,
- // since this may trigger a JVM exception
- X11Util.shutdown( false, DEBUG );
+ *
+ x11GLXDynamicLookupHelper.destroy();
+ */
+ x11GLXDynamicLookupHelper = null;
}
+ @Override
public final GLDynamicLookupHelper getGLDynamicLookupHelper(int profile) {
return x11GLXDynamicLookupHelper;
}
private X11GraphicsDevice defaultDevice;
private SharedResourceRunner sharedResourceRunner;
- private HashMap<String /* connection */, SharedResourceRunner.Resource> sharedMap;
+ 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;
- X11DummyGLXDrawable drawable;
- X11GLXContext context;
- String glXServerVendorName;
- boolean isGLXServerVendorATI;
- boolean isGLXServerVendorNVIDIA;
- VersionNumber glXServerVersion;
- boolean glXServerVersionOneOneCapable;
- boolean glXServerVersionOneThreeCapable;
- boolean glXMultisampleAvailable;
+ GLDrawableImpl drawable;
+ GLContextImpl context;
SharedResource(X11GraphicsDevice dev, X11GraphicsScreen scrn,
- X11DummyGLXDrawable draw, X11GLXContext ctx,
+ GLDrawableImpl draw, GLContextImpl ctx,
VersionNumber glXServerVer, String glXServerVendor, boolean glXServerMultisampleAvail) {
device = dev;
screen = scrn;
drawable = draw;
context = ctx;
glXServerVersion = glXServerVer;
- glXServerVersionOneOneCapable = glXServerVersion.compareTo(versionOneOne) >= 0 ;
- glXServerVersionOneThreeCapable = glXServerVersion.compareTo(versionOneThree) >= 0 ;
+ glXServerVersionOneOneCapable = glXServerVersion.compareTo(versionOneOne) >= 0 ;
+ glXServerVersionOneThreeCapable = glXServerVersion.compareTo(versionOneThree) >= 0 ;
glXServerVendorName = glXServerVendor;
isGLXServerVendorATI = GLXUtil.isVendorATI(glXServerVendorName);
isGLXServerVendorNVIDIA = GLXUtil.isVendorNVIDIA(glXServerVendorName);
glXMultisampleAvailable = glXServerMultisampleAvail;
}
+ @Override
+ public final boolean isValid() {
+ return null != context;
+ }
+ @Override
final public AbstractGraphicsDevice getDevice() { return device; }
+ @Override
final public AbstractGraphicsScreen getScreen() { return screen; }
+ @Override
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; }
@@ -191,60 +222,72 @@ 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);
- }
+ return sharedMap.put(connection, resource);
}
+ @Override
public SharedResourceRunner.Resource mapGet(String connection) {
- synchronized(sharedMap) {
- return sharedMap.get(connection);
- }
+ return sharedMap.get(connection);
}
+ @Override
public Collection<SharedResourceRunner.Resource> mapValues() {
- synchronized(sharedMap) {
- return sharedMap.values();
+ return sharedMap.values();
+ }
+
+ @Override
+ public boolean isDeviceSupported(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) {
- X11GraphicsDevice sharedDevice =
- new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- true); // own non-shared display connection, no locking
- // new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT,
- // NativeWindowFactory.getNullToolkitLock(), true); // own non-shared display connection, no locking
+ final X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.openDisplay(connection), AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
sharedDevice.lock();
try {
- if(!GLXUtil.isGLXAvailableOnServer(sharedDevice)) {
- throw new GLException("GLX not available on device/server: "+sharedDevice);
- }
- GLXUtil.initGLXClientDataSingleton(sharedDevice);
+ final X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, sharedDevice.getDefaultScreen());
+
+ 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());
- }
- X11GraphicsScreen sharedScreen = new X11GraphicsScreen(sharedDevice, 0);
+ final boolean glXServerMultisampleAvailable = GLXUtil.isMultisampleAvailable(GLX.glXQueryServerString(sharedDevice.getHandle(), 0, GLX.GLX_EXTENSIONS));
- 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);
}
- X11DummyGLXDrawable sharedDrawable = X11DummyGLXDrawable.create(sharedScreen, X11GLXDrawableFactory.this, glp);
- if (null == sharedDrawable) {
- throw new GLException("Couldn't create shared drawable for screen: "+sharedScreen+", "+glp);
+
+ 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);
}
- X11GLXContext sharedContext = (X11GLXContext) sharedDrawable.createContext(null);
+ 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 {
@@ -252,19 +295,22 @@ 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());
System.err.println("GLX Client Multisample: " + GLXUtil.isClientMultisampleAvailable());
}
- return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext,
- glXServerVersion, glXServerVendorName,
+ return new SharedResource(sharedDevice, sharedScreen, sharedDrawable, sharedContext,
+ glXServerVersion, glXServerVendorName,
glXServerMultisampleAvailable && GLXUtil.isClientMultisampleAvailable());
} catch (Throwable t) {
throw new GLException("X11GLXDrawableFactory - Could not initialize shared resources for "+connection, t);
@@ -273,6 +319,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
public void releaseSharedResource(SharedResourceRunner.Resource shared) {
SharedResource sr = (SharedResource) shared;
if (DEBUG) {
@@ -285,14 +332,14 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
if (null != sr.context) {
- // may cause JVM SIGSEGV:
- sr.context.destroy();
+ // 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;
}
if (null != sr.drawable) {
// may cause JVM SIGSEGV:
- sr.drawable.destroy();
+ sr.drawable.setRealized(false);
sr.drawable = null;
}
@@ -308,10 +355,12 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
}
+ @Override
public final AbstractGraphicsDevice getDefaultDevice() {
return defaultDevice;
}
+ @Override
public final boolean getIsDeviceCompatible(AbstractGraphicsDevice device) {
if(null != x11GLXDynamicLookupHelper && device instanceof X11GraphicsDevice) {
return true;
@@ -319,64 +368,38 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return false;
}
+ @Override
protected final Thread getSharedResourceThread() {
return sharedResourceRunner.start();
}
-
- 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;
- }
-
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(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) {
return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
}
+ @Override
protected final GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
}
- return new X11OnscreenGLXDrawable(this, target);
+ return new X11OnscreenGLXDrawable(this, target, false);
}
+ @Override
protected final GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -412,7 +435,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
public final boolean isGLXMultisampleAvailable(AbstractGraphicsDevice device) {
- if(null != device) {
+ if(null != device) {
SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
if(null!=sr) {
return sr.isGLXMultisampleAvailable();
@@ -422,47 +445,48 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
public final VersionNumber getGLXVersionNumber(AbstractGraphicsDevice device) {
- if(null != device) {
+ if(null != device) {
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) {
- if(null != device) {
+ if(null != device) {
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) {
- if(null != device) {
+ if(null != device) {
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;
}
}
return false;
}
- public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
+ @Override
+ public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device, GLProfile glp) {
if(null == device) {
SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(defaultDevice);
if(null!=sr) {
@@ -472,68 +496,72 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return isGLXVersionGreaterEqualOneThree(device);
}
- protected final NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- if(null == deviceReq) {
- throw new InternalError("deviceReq is null");
- }
- final SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(deviceReq);
- if(null==sr) {
- throw new InternalError("No SharedResource for: "+deviceReq);
+ @Override
+ protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) {
+ final X11GraphicsDevice device;
+ if( createNewDevice || !(deviceReq instanceof X11GraphicsDevice) ) {
+ device = new X11GraphicsDevice(X11Util.openDisplay(deviceReq.getConnection()), deviceReq.getUnitID(), true /* owner */);
+ } else {
+ device = (X11GraphicsDevice) deviceReq;
}
- final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sr.getScreen();
- final AbstractGraphicsDevice sharedDevice = sharedScreen.getDevice(); // should be same ..
-
- // create screen/device pair - Null X11 locking, due to private non-shared Display handle
- final X11GraphicsDevice device = new X11GraphicsDevice(X11Util.openDisplay(sharedDevice.getConnection()), AbstractGraphicsDevice.DEFAULT_UNIT, NativeWindowFactory.getNullToolkitLock(), true);
- final X11GraphicsScreen screen = new X11GraphicsScreen(device, sharedScreen.getIndex());
-
- WrappedSurface ns = new WrappedSurface(
- X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen) );
- if(ns != null) {
- ns.surfaceSizeChanged(width, height);
+ 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);
}
- return ns;
+ return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
}
- protected final ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
- // FIXME device/windowHandle -> screen ?!
- X11GraphicsDevice device = (X11GraphicsDevice) adevice;
- X11GraphicsScreen screen = new X11GraphicsScreen(device, 0);
- X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen);
- WrappedSurface ns = new WrappedSurface(cfg, windowHandle);
- return ns;
+ @Override
+ public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, 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(), true /* owner */);
+ final X11GraphicsScreen screen = new X11GraphicsScreen(device, screenIdx);
+ final int xvisualID = X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle);
+ if(VisualIDHolder.VID_UNDEFINED == xvisualID) {
+ throw new GLException("Undefined VisualID of window 0x"+Long.toHexString(windowHandle)+", window probably invalid");
+ }
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": visualID 0x"+Integer.toHexString(xvisualID));
+ }
+ final X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, xvisualID);
+ if(DEBUG) {
+ System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg);
+ }
+ return new WrappedSurface(cfg, windowHandle, upstream, true);
+ }
+
+ @Override
protected final GLContext createExternalGLContextImpl() {
return X11ExternalGLXContext.create(this, null);
}
+ @Override
public final boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) {
- return canCreateGLPbuffer(device);
+ return canCreateGLPbuffer(device, null /* GLProfile not used for query on X11 */);
}
+ @Override
protected final GLDrawable createExternalGLDrawableImpl() {
return X11ExternalGLXDrawable.create(this, null);
}
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//----------------------------------------------------------------------
// Gamma-related functionality
//
private boolean gotGammaRampLength;
private int gammaRampLength;
+ @Override
protected final synchronized int getGammaRampLength() {
if (gotGammaRampLength) {
return gammaRampLength;
@@ -556,6 +584,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return gammaRampLength;
}
+ @Override
protected final boolean setGammaRamp(float[] ramp) {
long display = getOrCreateSharedDpy(defaultDevice);
if(0 == display) {
@@ -577,6 +606,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return res;
}
+ @Override
protected final Buffer getGammaRamp() {
long display = getOrCreateSharedDpy(defaultDevice);
if(0 == display) {
@@ -607,6 +637,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return rampData;
}
+ @Override
protected final void resetGammaRamp(Buffer originalGammaRamp) {
if (originalGammaRamp == null) {
return; // getGammaRamp failed originally
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDynamicLibraryBundleInfo.java
index 108c157a8..951174f71 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,19 +55,10 @@ 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() {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index 0af62394c..ee3e1a3d7 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,9 +33,13 @@
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;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
@@ -51,22 +55,63 @@ 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;
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,
+ X11GLXGraphicsConfiguration(X11GraphicsScreen screen,
X11GLCapabilities capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
super(screen, capsChosen, capsRequested, capsChosen.getXVisualInfo());
this.chooser=chooser;
}
+ @Override
+ public Object clone() {
+ return super.clone();
+ }
+
+ public final long getFBConfig() {
+ return ((X11GLCapabilities)capabilitiesChosen).getFBConfig();
+ }
+ 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!
+ final X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
+ GraphicsConfigurationFactory.getFactory(getScreen().getDevice(), aChosenCaps).chooseGraphicsConfiguration(
+ aChosenCaps, getRequestedCapabilities(), chooser, getScreen(), VisualIDHolder.VID_UNDEFINED);
+ if(null!=newConfig) {
+ // FIXME: setScreen( ... );
+ setXVisualInfo(newConfig.getXVisualInfo());
+ setChosenCapabilities(newConfig.getChosenCapabilities());
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration updated:"+this);
+ }
+ } else {
+ throw new GLException("No native VisualID pre-chosen and update failed: "+this);
+ }
+ } else if (DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.updateGraphicsConfiguration kept:"+this);
+ }
+ }
+
static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) {
- final long display = x11Screen.getDevice().getHandle();
+ final X11GraphicsDevice device = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = device.getHandle();
if(0==display) {
throw new GLException("Display null of "+x11Screen);
}
@@ -79,43 +124,16 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
glp = GLProfile.getDefault(x11Screen.getDevice());
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final X11GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(x11Screen.getDevice()));
+ 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());
}
- public Object clone() {
- return super.clone();
- }
-
- public final long getFBConfig() {
- return ((X11GLCapabilities)capabilitiesChosen).getFBConfig();
- }
- public final int getFBConfigID() {
- return ((X11GLCapabilities)capabilitiesChosen).getFBConfigID();
- }
-
- void updateGraphicsConfiguration() {
- X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration)
- GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(
- getChosenCapabilities(), getRequestedCapabilities(), chooser, getScreen());
- if(null!=newConfig) {
- // FIXME: setScreen( ... );
- setXVisualInfo(newConfig.getXVisualInfo());
- setChosenCapabilities(newConfig.getChosenCapabilities());
- if(DEBUG) {
- System.err.println("updateGraphicsConfiguration: "+this);
- }
- }
- }
-
- static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps,
- boolean forFBAttr,
- boolean isMultisampleAvailable,
- long display,
- int screen)
+ static IntBuffer GLCapabilities2AttribList(GLCapabilitiesImmutable caps,
+ boolean forFBAttr, boolean isMultisampleAvailable,
+ long display, int screen)
{
int colorDepth = (caps.getRedBits() +
caps.getGreenBits() +
@@ -123,123 +141,124 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
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[idx++] = caps.isOnscreen() ? ( GLX.GLX_WINDOW_BIT ) : ( caps.isPBuffer() ? GLX.GLX_PBUFFER_BIT : GLX.GLX_PIXMAP_BIT ) ;
- }
+ res.put(idx++, GLX.GLX_DRAWABLE_TYPE);
+
+ final int surfaceType;
+ if( caps.isOnscreen() ) {
+ surfaceType = GLX.GLX_WINDOW_BIT;
+ } else if( caps.isFBO() ) {
+ surfaceType = GLX.GLX_WINDOW_BIT; // native replacement!
+ } else if( caps.isPBuffer() ) {
+ surfaceType = GLX.GLX_PBUFFER_BIT;
+ } else if( caps.isBitmap() ) {
+ surfaceType = GLX.GLX_PIXMAP_BIT;
+ } else {
+ throw new GLException("no surface type set in caps: "+caps);
+ }
+ res.put(idx++, surfaceType);
- if (forFBAttr) {
- res[idx++] = GLX.GLX_RENDER_TYPE;
- res[idx++] = GLX.GLX_RGBA_BIT;
+ 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) {
+
+ static boolean GLXFBConfigIDValid(long display, int screen, int fbcfgid) {
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)) {
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp)) {
return false;
}
return true;
}
- static int FBCfgDrawableTypeBits(final long display, final long fbcfg) {
+ static int FBCfgDrawableTypeBits(final X11GraphicsDevice device, final long fbcfg) {
int val = 0;
- int[] tmp = new int[1];
- int fbtype = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0);
+ final IntBuffer tmp = Buffers.newDirectIntBuffer(1);
+ int fbtype = glXGetFBConfig(device.getHandle(), fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp);
if ( 0 != ( fbtype & GLX.GLX_WINDOW_BIT ) ) {
- val |= GLGraphicsConfigurationUtil.WINDOW_BIT;
+ val |= GLGraphicsConfigurationUtil.WINDOW_BIT |
+ GLGraphicsConfigurationUtil.FBO_BIT;
}
if ( 0 != ( fbtype & GLX.GLX_PIXMAP_BIT ) ) {
val |= GLGraphicsConfigurationUtil.BITMAP_BIT;
@@ -250,19 +269,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return val;
}
- static X11GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg,
- boolean relaxed, boolean onscreen, boolean usePBuffer,
- boolean isMultisampleAvailable) {
- ArrayList bucket = new ArrayList();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- if( GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, winattrmask, isMultisampleAvailable) ) {
- return (X11GLCapabilities) bucket.get(0);
- } else if ( relaxed && GLXFBConfig2GLCapabilities(bucket, glp, display, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
- return (X11GLCapabilities) bucket.get(0);
- }
- return null;
- }
-
static XRenderDirectFormat XVisual2XRenderMask(long dpy, long visual) {
XRenderPictFormat renderPictFmt = X11Lib.XRenderFindVisualFormat(dpy, visual);
if(null == renderPictFmt) {
@@ -270,70 +276,135 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
return renderPictFmt.getDirect();
}
+ static XRenderDirectFormat XVisual2XRenderMask(long dpy, long visual, XRenderPictFormat dest) {
+ if( !X11Lib.XRenderFindVisualFormat(dpy, visual, dest) ) {
+ return null;
+ } else {
+ return dest.getDirect();
+ }
+ }
+
+ 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 boolean GLXFBConfig2GLCapabilities(ArrayList capsBucket,
- GLProfile glp, long display, long fbcfg,
- int winattrmask, boolean isMultisampleAvailable) {
- final int allDrawableTypeBits = FBCfgDrawableTypeBits(display, fbcfg);
+ static List<GLCapabilitiesImmutable> GLXFBConfig2GLCapabilities(final X11GraphicsDevice device, final GLProfile glp, final PointerBuffer fbcfgsL,
+ final int winattrmask, final boolean isMultisampleAvailable, 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;
- int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
- XVisualInfo visualInfo = GLX.glXGetVisualFromFBConfig(display, fbcfg);
+ final int fbcfgid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg);
+ 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));
}
// onscreen must have an XVisualInfo
- drawableTypeBits = drawableTypeBits & ~GLGraphicsConfigurationUtil.WINDOW_BIT;
+ drawableTypeBits &= ~(GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.FBO_BIT);
}
-
if( 0 == drawableTypeBits ) {
- return false;
+ 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)) {
- return false;
+ 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 false; // no RGBA -> color index not supported
- }
-
- GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp);
- 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.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0));
- res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0));
- 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));
- if (isMultisampleAvailable) {
- res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0);
- res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0));
+ 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 XRenderDirectFormat xrmask = ( null != visualInfo ) ?
- XVisual2XRenderMask( display, visualInfo.getVisual() ) :
+
+ 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) {
+ caps.setSampleBuffers(values.get(j++) != 0);
+ caps.setNumSamples (values.get(j++));
+ }
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);
}
-
- try {
- res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE);
- } catch (Exception e) {}
-
- return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits );
+ // 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) {
@@ -344,26 +415,27 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) {
+ static int glXGetFBConfig(long display, long cfg, int attrib, IntBuffer tmp) {
if (display == 0) {
throw new GLException("No display connection");
}
- int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp, tmp_offset);
+ int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp);
if (res != 0) {
throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res));
}
- return tmp[tmp_offset];
+ return tmp.get(tmp.position());
}
static int glXFBConfig2FBConfigID(long display, long cfg) {
- int[] tmpID = new int[1];
- return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID, 0);
+ final IntBuffer tmpID = Buffers.newDirectIntBuffer(1);
+ return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID);
}
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);
+ final IntBuffer attribs = Buffers.newDirectIntBuffer(new int[] { GLX.GLX_FBCONFIG_ID, id, 0 });
+ final IntBuffer count = Buffers.newDirectIntBuffer(1);
+ count.put(0, -1);
+ PointerBuffer fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, count);
if (fbcfgsL == null || fbcfgsL.limit()<1) {
return 0;
}
@@ -379,7 +451,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
XVisualInfo[] infos = X11Lib.XGetVisualInfo(display, X11Lib.VisualIDMask, template, count, 0);
if (infos == null || infos.length == 0) {
return null;
- }
+ }
XVisualInfo res = XVisualInfo.create(infos[0]);
if (DEBUG) {
System.err.println("Fetched XVisualInfo for visual ID " + toHexString(visualID));
@@ -388,57 +460,49 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
return res;
}
- static boolean XVisualInfo2GLCapabilities(ArrayList capsBucket,
- GLProfile glp, long display, XVisualInfo info,
- final int winattrmask, boolean isMultisampleEnabled) {
- final int allDrawableTypeBits = GLGraphicsConfigurationUtil.WINDOW_BIT | GLGraphicsConfigurationUtil.BITMAP_BIT ;
+ static X11GLCapabilities XVisualInfo2GLCapabilities(final X11GraphicsDevice device, GLProfile glp, XVisualInfo info,
+ final int winattrmask, boolean isMultisampleEnabled) {
+ final int allDrawableTypeBits = GLGraphicsConfigurationUtil.WINDOW_BIT |
+ GLGraphicsConfigurationUtil.BITMAP_BIT |
+ GLGraphicsConfigurationUtil.FBO_BIT ;
+
final int drawableTypeBits = winattrmask & allDrawableTypeBits;
if( 0 == drawableTypeBits ) {
- return false;
+ return null;
}
- int[] tmp = new int[1];
- int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0);
+ final long display = device.getHandle();
+ 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 false;
+ 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");
}
- return false;
+ return null;
}
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.
- 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));
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 );
@@ -448,8 +512,20 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setTransparentBlueValue(xrmask.getBlueMask());
res.setTransparentAlphaValue(alphaMask);
}
-
- return GLGraphicsConfigurationUtil.addGLCapabilitiesPermutations(capsBucket, res, drawableTypeBits);
+ // 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));
+ 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) {
@@ -462,17 +538,18 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
}
}
- static int glXGetConfig(long display, XVisualInfo info, int attrib, int[] tmp, int tmp_offset) {
+ static int glXGetConfig(long display, XVisualInfo info, int attrib, IntBuffer tmp) {
if (display == 0) {
throw new GLException("No display connection");
}
- int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset);
+ 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 0ec2f234c..1f92960bc 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
@@ -40,6 +40,7 @@ import javax.media.nativewindow.CapabilitiesChooser;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.GraphicsConfigurationFactory;
import javax.media.nativewindow.VisualIDHolder;
+import javax.media.nativewindow.VisualIDHolder.VIDType;
import javax.media.opengl.DefaultGLCapabilitiesChooser;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
@@ -48,6 +49,7 @@ 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;
@@ -57,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;
@@ -73,20 +76,25 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static GraphicsConfigurationFactory fallbackX11GraphicsConfigurationFactory = null;
static void registerFactory() {
final GraphicsConfigurationFactory newFactory = new X11GLXGraphicsConfigurationFactory();
- final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, newFactory);
+ final GraphicsConfigurationFactory oldFactory = GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, GLCapabilitiesImmutable.class, newFactory);
if(oldFactory == newFactory) {
throw new InternalError("GraphicsConfigurationFactory lifecycle impl. error");
}
- if(null == oldFactory) {
- throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ if(null != oldFactory) {
+ fallbackX11GraphicsConfigurationFactory = oldFactory;
+ } else {
+ fallbackX11GraphicsConfigurationFactory = GraphicsConfigurationFactory.getFactory(com.jogamp.nativewindow.x11.X11GraphicsDevice.class, CapabilitiesImmutable.class);
+ if( null == fallbackX11GraphicsConfigurationFactory ) {
+ throw new InternalError("Missing fallback GraphicsConfigurationFactory");
+ }
}
- fallbackX11GraphicsConfigurationFactory = oldFactory;
}
private X11GLXGraphicsConfigurationFactory() {
}
+ @Override
protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
- CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen) {
+ CapabilitiesImmutable capsChosen, CapabilitiesImmutable capsRequested, CapabilitiesChooser chooser, AbstractGraphicsScreen absScreen, int nativeVisualID) {
if (!(absScreen instanceof X11GraphicsScreen)) {
throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here");
}
@@ -102,38 +110,42 @@ 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) {
System.err.println("No GLX available, fallback to "+fallbackX11GraphicsConfigurationFactory.getClass().getSimpleName()+" for: "+absScreen);
}
- return fallbackX11GraphicsConfigurationFactory.chooseGraphicsConfiguration(capsChosen, capsRequested, chooser, absScreen);
+ 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);
+ (GLCapabilitiesChooser)chooser, (X11GraphicsScreen)absScreen, nativeVisualID);
}
protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
- X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ 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 X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable();
- final GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities();
- final GLProfile glp = capsChosen.getGLProfile();
+ 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);
@@ -146,33 +158,35 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
// Utilizing FBConfig
//
- AbstractGraphicsDevice absDevice = x11Screen.getDevice();
- long display = absDevice.getHandle();
+ final X11GraphicsDevice absDevice = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = absDevice.getHandle();
- int screen = x11Screen.getIndex();
- int[] count = { -1 };
- ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
+ final int screen = x11Screen.getIndex();
+ 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;
}
for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
- if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
+ final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(absDevice, glProfile, fbcfgsL.get(i), GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable);
+ if(null != caps) {
+ availableCaps.add(caps);
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
}
}
return availableCaps;
}
static List<GLCapabilitiesImmutable> getAvailableGLCapabilitiesXVisual(X11GraphicsScreen x11Screen, GLProfile glProfile, boolean isMultisampleAvailable) {
- AbstractGraphicsDevice absDevice = x11Screen.getDevice();
- long display = absDevice.getHandle();
+ final X11GraphicsDevice absDevice = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = absDevice.getHandle();
int screen = x11Screen.getIndex();
@@ -185,10 +199,11 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
ArrayList<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
for (int i = 0; i < infos.length; i++) {
- if( !X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(availableCaps, glProfile, display, infos[i], GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable) ) {
- if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid()));
- }
+ final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(absDevice, glProfile, infos[i], GLGraphicsConfigurationUtil.ALL_BITS, isMultisampleAvailable);
+ if(null != caps) {
+ availableCaps.add(caps);
+ } if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.getAvailableGLCapabilitiesXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid()));
}
}
return availableCaps;
@@ -198,42 +213,46 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (x11Screen == null) {
throw new IllegalArgumentException("AbstractGraphicsScreen is null");
}
-
if (capsChosen == null) {
capsChosen = new GLCapabilities(null);
}
- X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
+ X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory.canCreateGLPbuffer(x11Device) );
- boolean usePBuffer = capsChosen.isPBuffer();
-
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, factory, x11Device);
+ final boolean usePBuffer = !capsChosen.isOnscreen() && capsChosen.isPBuffer();
+
X11GLXGraphicsConfiguration res = null;
- if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) {
- res = chooseGraphicsConfigurationFBConfig(capsChosen, capsReq, chooser, x11Screen);
- }
- if(null==res) {
- if(usePBuffer) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+capsChosen);
+ x11Device.lock();
+ try {
+ 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);
+ }
+ res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen, xvisualID);
}
- res = chooseGraphicsConfigurationXVisual(capsChosen, capsReq, chooser, x11Screen);
+ } finally {
+ x11Device.unlock();
}
if(null==res) {
- throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+capsChosen);
+ throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for visualID "+toHexString(xvisualID)+", "+x11Screen+", "+capsChosen);
}
if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+capsChosen+"): "+res);
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic(visualID "+toHexString(xvisualID)+", "+x11Screen+","+capsChosen+"): "+res);
}
return res;
}
static X11GLXGraphicsConfiguration fetchGraphicsConfigurationFBConfig(X11GraphicsScreen x11Screen, int fbID, GLProfile glp) {
- final AbstractGraphicsDevice absDevice = x11Screen.getDevice();
- final long display = absDevice.getHandle();
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
+ final long display = x11Device.getHandle();
final int screen = x11Screen.getIndex();
final long fbcfg = X11GLXGraphicsConfiguration.glXFBConfigID2FBConfig(display, screen, fbID);
@@ -244,55 +263,60 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
return null;
}
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
-
- final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, factory.isGLXMultisampleAvailable(absDevice));
+
+ final X11GLCapabilities caps = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(x11Device, glp, fbcfg, GLGraphicsConfigurationUtil.ALL_BITS, factory.isGLXMultisampleAvailable(x11Device));
return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser());
}
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
int recommendedIndex = -1;
PointerBuffer fbcfgsL = null;
GLProfile glProfile = capsChosen.getGLProfile();
- boolean onscreen = capsChosen.isOnscreen();
- boolean usePBuffer = capsChosen.isPBuffer();
// Utilizing FBConfig
//
- AbstractGraphicsDevice absDevice = x11Screen.getDevice();
- long display = absDevice.getHandle();
+ X11GraphicsDevice x11Device = (X11GraphicsDevice) x11Screen.getDevice();
+ long display = x11Device.getHandle();
int screen = x11Screen.getIndex();
-
- final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
- final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(absDevice);
- int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen);
- int[] count = { -1 };
- ArrayList/*<X11GLCapabilities>*/ availableCaps = new ArrayList();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer);
- // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice
- fbcfgsL = GLX.glXChooseFBConfig(display, screen, attribs, 0, count, 0);
- if (fbcfgsL != null && fbcfgsL.limit()>0) {
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
- if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (1): ("+x11Screen+","+capsChosen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
- }
- }
+ final X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory();
+ final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(x11Device);
+ 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, 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
@@ -300,23 +324,48 @@ 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;
}
+ 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));
+ }
+ }
- for (int i = 0; i < fbcfgsL.limit(); i++) {
- if( !X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(availableCaps, glProfile, display, fbcfgsL.get(i), winattrmask, isMultisampleAvailable) ) {
- if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid (2): ("+x11Screen+"): fbcfg: "+toHexString(fbcfgsL.get(i)));
- }
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) { // implies !hasGLXChosenCaps
+ for(int i=0; i<availableCaps.size(); ) {
+ final VisualIDHolder vidh = availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: post filter visualID "+toHexString(xvisualID )+" no config found, failed - return null");
}
+ return null;
+ } else if(DEBUG) {
+ 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");
@@ -332,32 +381,36 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
private static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilitiesImmutable capsChosen,
GLCapabilitiesImmutable capsReq,
GLCapabilitiesChooser chooser,
- X11GraphicsScreen x11Screen) {
+ X11GraphicsScreen x11Screen, int xvisualID) {
if (chooser == null) {
chooser = new DefaultGLCapabilitiesChooser();
}
GLProfile glProfile = capsChosen.getGLProfile();
- final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */);
- ArrayList availableCaps = new ArrayList();
+ final int winattrmask = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(capsChosen.isOnscreen(), capsChosen.isFBO(), false /* pbuffer */, capsChosen.isBitmap());
+ List<GLCapabilitiesImmutable> availableCaps = new ArrayList<GLCapabilitiesImmutable>();
int recommendedIndex = -1;
- AbstractGraphicsDevice absDevice = x11Screen.getDevice();
+ 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 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
- XVisualInfo recommendedVis = GLX.glXChooseVisual(display, screen, attribs, 0);
- if (DEBUG) {
- System.err.print("glXChooseVisual recommended ");
- if (recommendedVis == null) {
- System.err.println("null visual");
- } else {
- System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ // skipped if xvisualID is given
+ if( VisualIDHolder.VID_UNDEFINED == xvisualID ) {
+ recommendedVis = GLX.glXChooseVisual(display, screen, attribs);
+ if (DEBUG) {
+ System.err.print("glXChooseVisual recommended ");
+ if (recommendedVis == null) {
+ System.err.println("null visual");
+ } else {
+ System.err.println("visual id " + toHexString(recommendedVis.getVisualid()));
+ }
}
}
@@ -371,15 +424,41 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
for (int i = 0; i < infos.length; i++) {
- if( !X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(availableCaps, glProfile, display, infos[i], winattrmask, isMultisampleAvailable) ) {
- if(DEBUG) {
- System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid()));
- }
- } else {
+ final GLCapabilitiesImmutable caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(absDevice, glProfile, infos[i], winattrmask, isMultisampleAvailable);
+ if( null != caps ) {
+ availableCaps.add(caps);
// Attempt to find the visual chosenIndex by glXChooseVisual, if not translucent
if (capsChosen.isBackgroundOpaque() && recommendedVis != null && recommendedVis.getVisualid() == infos[i].getVisualid()) {
recommendedIndex = availableCaps.size() - 1;
}
+ } else if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: XVisual invalid: ("+x11Screen+"): fbcfg: "+toHexString(infos[i].getVisualid()));
+ }
+ }
+
+ if(DEBUG) {
+ System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual: got configs: "+availableCaps.size());
+ for(int i=0; i<availableCaps.size(); i++) {
+ System.err.println(i+": "+availableCaps.get(i));
+ }
+ }
+
+ if( VisualIDHolder.VID_UNDEFINED != xvisualID ) {
+ for(int i=0; i<availableCaps.size(); ) {
+ VisualIDHolder vidh = availableCaps.get(i);
+ if(vidh.getVisualID(VIDType.X11_XVISUAL) != xvisualID ) {
+ availableCaps.remove(i);
+ } else {
+ i++;
+ }
+ }
+ if(0==availableCaps.size()) {
+ if(DEBUG) {
+ 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());
}
}
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 ce5d466d4..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 b2a8326cb..9da189290 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.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,19 +29,21 @@
* 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.nativewindow.*;
-import javax.media.opengl.*;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
public class X11OnscreenGLXDrawable extends X11GLXDrawable {
/** GLXWindow can't be made current on AWT with NVidia driver, hence disabled for now */
@@ -49,33 +51,38 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
long glXWindow; // GLXWindow, a GLXDrawable representation
boolean useGLXWindow;
- protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component) {
- super(factory, component, false);
+ protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeSurface component, boolean realized) {
+ super(factory, component, realized);
glXWindow=0;
useGLXWindow=false;
+ if(realized) {
+ createHandle();
+ }
}
- @SuppressWarnings("unused")
@Override
public long getHandle() {
- if(USE_GLXWINDOW && useGLXWindow) {
- return glXWindow;
- }
+ if(USE_GLXWINDOW) {
+ if(useGLXWindow) {
+ return glXWindow;
+ }
+ }
return super.getHandle();
}
- @SuppressWarnings("unused")
@Override
protected void destroyHandle() {
- if(USE_GLXWINDOW && 0!=glXWindow) {
- GLX.glXDestroyWindow(getNativeSurface().getDisplayHandle(), glXWindow);
- glXWindow = 0;
- useGLXWindow=false;
+ if(USE_GLXWINDOW) {
+ if(0!=glXWindow) {
+ GLX.glXDestroyWindow(getNativeSurface().getDisplayHandle(), glXWindow);
+ glXWindow = 0;
+ useGLXWindow=false;
+ }
}
}
@Override
- protected final void updateHandle() {
+ protected final void createHandle() {
if(USE_GLXWINDOW) {
X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
if(config.getFBConfig()>=0) {
@@ -84,7 +91,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
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));
}
@@ -95,7 +102,8 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new X11OnscreenGLXContext(this, 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 765a8207a..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
+++ /dev/null
@@ -1,64 +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);
- }
-
- public void bindPbufferToTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
- public void releasePbufferFromTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
-
- 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 da7b535cb..0e771fd0f 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.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,32 +29,38 @@
* 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.*;
-import javax.media.nativewindow.*;
+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.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.nio.Buffers;
public class X11PbufferGLXDrawable extends X11GLXDrawable {
protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeSurface target) {
- /* GLCapabilities caps,
+ /* GLCapabilities caps,
GLCapabilitiesChooser chooser,
int width, int height */
super(factory, target, false);
}
- protected void destroyImpl() {
- setRealized(false);
- }
-
+ @Override
protected void setRealizedImpl() {
if(realized) {
createPbuffer();
@@ -63,8 +69,9 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new X11PbufferGLXContext(this, shareWith);
+ return new X11GLXContext(this, shareWith);
}
protected void destroyPbuffer() {
@@ -72,69 +79,50 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
if (ns.getSurfaceHandle() != 0) {
GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle());
}
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
+ if (DEBUG) {
+ System.err.println(getThreadName()+": Destroyed pbuffer " + this);
+ }
}
private void createPbuffer() {
- X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
- AbstractGraphicsScreen aScreen = config.getScreen();
- AbstractGraphicsDevice aDevice = aScreen.getDevice();
- long display = aDevice.getHandle();
+ final MutableSurface ms = (MutableSurface) getNativeSurface();
+ final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ms.getGraphicsConfiguration();
+ final AbstractGraphicsScreen aScreen = config.getScreen();
+ final AbstractGraphicsDevice aDevice = aScreen.getDevice();
+ 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");
}
- NativeSurface ns = getNativeSurface();
-
- 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[5];
+ IntBuffer iattributes = Buffers.newDirectIntBuffer(7);
- iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH;
- iattributes[niattribs++] = ns.getWidth();
- iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT;
- iattributes[niattribs++] = ns.getHeight();
- iattributes[niattribs++] = 0;
+ iattributes.put(niattribs++, GLX.GLX_PBUFFER_WIDTH);
+ iattributes.put(niattribs++, ms.getWidth());
+ iattributes.put(niattribs++, GLX.GLX_PBUFFER_HEIGHT);
+ iattributes.put(niattribs++, ms.getHeight());
+ 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);
+ 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");
}
// Set up instance variables
- ((SurfaceChangeable)ns).setSurfaceHandle(pbuffer);
-
- // Determine the actual width and height we were able to create.
- int[] tmp = new int[1];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0);
- int width = tmp[0];
- GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0);
- int height = tmp[0];
- ((SurfaceChangeable)ns).surfaceSizeChanged(width, height);
-
+ 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 e19dfd1b3..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
+++ /dev/null
@@ -1,70 +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);
- }
-
- 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;
- }
-
- public int getOffscreenContextReadBuffer() {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
- if (caps.getDoubleBuffered()) {
- return GL.GL_BACK;
- }
- return GL.GL_FRONT;
- }
-
- 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 7dae20f80..c1388db8a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.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,27 @@
* 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.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.nativewindow.x11.*;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.MutableSurface;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+
+import jogamp.nativewindow.x11.X11Lib;
+import jogamp.nativewindow.x11.XVisualInfo;
public class X11PixmapGLXDrawable extends X11GLXDrawable {
private long pixmap;
@@ -51,10 +58,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
super(factory, target, false);
}
- protected void destroyImpl() {
- setRealized(false);
- }
-
+ @Override
protected void setRealizedImpl() {
if(realized) {
createPixmap();
@@ -63,10 +67,11 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
}
}
+ @Override
public GLContext createContext(GLContext shareWith) {
- return new X11PixmapGLXContext(this, shareWith);
+ return new X11GLXContext(this, shareWith);
}
-
+
private void createPixmap() {
NativeSurface ns = getNativeSurface();
X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ns.getGraphicsConfiguration();
@@ -88,9 +93,9 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
pixmap = 0;
throw new GLException("glXCreateGLXPixmap failed");
}
- ((SurfaceChangeable)ns).setSurfaceHandle(drawable);
+ ((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,7 +109,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
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));
}
@@ -128,7 +133,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
X11Lib.XFreePixmap(display, pixmap);
drawable = 0;
pixmap = 0;
- ((SurfaceChangeable)ns).setSurfaceHandle(0);
+ ((MutableSurface)ns).setSurfaceHandle(0);
display = 0;
}
}