javauis/m3g_qt/javasrc/javax/microedition/m3g/Interface.java
changeset 35 85266cc22c7f
child 40 c6043ea9b06a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/m3g_qt/javasrc/javax/microedition/m3g/Interface.java	Fri Jun 11 13:33:44 2010 +0300
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+package javax.microedition.m3g;
+
+import java.lang.ref.WeakReference;
+import java.util.Hashtable;
+import org.eclipse.swt.widgets.Display;
+//#ifdef RD_JAVA_OMJ
+import com.nokia.mj.impl.rt.support.Finalizer;
+//#endif // RD_JAVA_OMJ
+
+/**
+ * M3G interface object. An interface is automatically created for
+ * each MIDlet using the 3D API to keep track of Java-side object
+ * lifetimes etc.
+ */
+class Interface
+{
+    //------------------------------------------------------------------
+    // Static data
+    //------------------------------------------------------------------
+
+    // Common class enumeration for Java and native code
+
+    private static final int ANIMATION_CONTROLLER = 0x01;
+    private static final int ANIMATION_TRACK      = 0x02;
+    private static final int APPEARANCE           = 0x03;
+    private static final int BACKGROUND           = 0x04;
+    private static final int CAMERA               = 0x05;
+    private static final int COMPOSITING_MODE     = 0x06;
+    private static final int FOG                  = 0x07;
+    private static final int GROUP                = 0x08;
+    private static final int IMAGE_2D             = 0x09;
+    private static final int INDEX_BUFFER         = 0x0A;
+    private static final int KEYFRAME_SEQUENCE    = 0x0B;
+    private static final int LIGHT                = 0x0C;
+    private static final int LOADER               = 0x0D;
+    private static final int MATERIAL             = 0x0E;
+    private static final int MESH                 = 0x0F;
+    private static final int MORPHING_MESH        = 0x10;
+    private static final int POLYGON_MODE         = 0x11;
+    private static final int RENDER_CONTEXT       = 0x12;
+    private static final int SKINNED_MESH         = 0x13;
+    private static final int SPRITE_3D            = 0x14;
+    private static final int TEXTURE_2D           = 0x15;
+    private static final int VERTEX_ARRAY         = 0x16;
+    private static final int VERTEX_BUFFER        = 0x17;
+    private static final int WORLD                = 0x18;
+
+    // Once created, the interface singleton currently remains in
+    // memory until VM exit.  By using a WeakReference here, with hard
+    // references stored in each object, it could be GC'd when no more
+    // objects exist, but that probably isn't worth the extra memory
+    // overhead.
+
+    //private static Hashtable s_instances = new Hashtable();
+    private static Interface instance = null;
+
+    //------------------------------------------------------------------
+    // Instance data
+    //------------------------------------------------------------------
+
+    /**
+     * Handle of the native interface object.
+     */
+    private int handle;
+
+    /**
+     * Global handle-to-Object3D map used to both find the Java
+     * counterparts of objects returned from the native methods, and
+     * keep certain objects from being garbage collected.
+     */
+    private final Hashtable liveObjects = new Hashtable();
+
+    /**
+     * Flag for shutdown signal
+     */
+    private boolean iShutdown = false;
+
+    /**
+     * Flag for native peer init state
+     */
+    private boolean iNativeInitialized = false;
+
+
+//#ifdef RD_JAVA_OMJ
+    private Finalizer mFinalizer;
+//#endif // RD_JAVA_OMJ
+
+    //------------------------------------------------------------------
+    // Constructors
+    //------------------------------------------------------------------
+
+    private Interface()
+    {
+
+        // Contruct native peer
+        initNativePeer();
+
+//#ifdef RD_JAVA_OMJ
+        mFinalizer = new Finalizer()
+        {
+            public void finalizeImpl()
+            {
+                doFinalize();
+            }
+        };
+//#else // RD_JAVA_OMJ
+//        Platform.registerFinalizer(this);
+//#endif // RD_JAVA_OMJ
+    }
+
+    //------------------------------------------------------------------
+    // Package methods
+    //------------------------------------------------------------------
+
+    /**
+     * Returns the M3G interface instance for the current MIDlet.
+     */
+    static final Interface getInstance()
+    {
+        if (instance == null)
+        {
+            instance = new Interface();
+        }
+        return instance;
+    }
+
+    /**
+     * Returns the native handle of the current Interface instance.
+     */
+    static final int getHandle()
+    {
+        getInstance().integrityCheck();
+        return getInstance().handle;
+    }
+
+    /**
+     * Registers an Object3D with this interface. The object is added
+     * to the global handle-to-object map, and the native finalization
+     * callback is set up. The handle of the object must already be
+     * set at this point!
+     */
+    static final void register(Object3D obj)
+    {
+        Platform.registerFinalizer(obj);
+        getInstance().liveObjects.put(new Integer(obj.handle),
+                                      new WeakReference(obj));
+    }
+
+    static final void register(Loader obj)
+    {
+        Platform.registerFinalizer(obj);
+        getInstance().liveObjects.put(new Integer(obj.handle),
+                                      new WeakReference(obj));
+    }
+
+    /**
+     * Finds an Object3D in the global handle-to-object map. Also
+     * removes dead objects (that is, null references) from the map
+     * upon encountering them.
+     */
+    static final Object3D findObject(int handle)
+    {
+        Interface self = getInstance();
+        Integer iHandle = new Integer(handle);
+        Object ref = self.liveObjects.get(iHandle);
+
+        if (ref != null)
+        {
+            Object3D obj = (Object3D)((WeakReference)ref).get();
+            if (obj == null)
+            {
+                self.liveObjects.remove(iHandle);
+            }
+            return obj;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the Java object representing a native object, or
+     * creates a new proxy/peer if one doesn't exist yet.
+     */
+    static final Object3D getObjectInstance(int handle)
+    {
+
+        // A zero handle equals null
+
+        if (handle == 0)
+        {
+            return null;
+        }
+
+        // Then try to find an existing Java representative for the
+        // object
+
+        Object3D obj = findObject(handle);
+        if (obj != null)
+        {
+            return obj;
+        }
+
+        // Not found, create a new Java object. Note that only
+        // non-abstract classes can possibly be returned.
+
+        switch (_getClassID(handle))
+        {
+        case ANIMATION_CONTROLLER:
+            return new AnimationController(handle);
+        case ANIMATION_TRACK:
+            return new AnimationTrack(handle);
+        case APPEARANCE:
+            return new Appearance(handle);
+        case BACKGROUND:
+            return new Background(handle);
+        case CAMERA:
+            return new Camera(handle);
+        case COMPOSITING_MODE:
+            return new CompositingMode(handle);
+        case FOG:
+            return new Fog(handle);
+        case GROUP:
+            return new Group(handle);
+        case IMAGE_2D:
+            return new Image2D(handle);
+        case INDEX_BUFFER:
+            return new TriangleStripArray(handle);
+        case KEYFRAME_SEQUENCE:
+            return new KeyframeSequence(handle);
+        case LIGHT:
+            return new Light(handle);
+            //case LOADER:
+        case MATERIAL:
+            return new Material(handle);
+        case MESH:
+            return new Mesh(handle);
+        case MORPHING_MESH:
+            return new MorphingMesh(handle);
+        case POLYGON_MODE:
+            return new PolygonMode(handle);
+            //case RENDER_CONTEXT:
+        case SKINNED_MESH:
+            return new SkinnedMesh(handle);
+        case SPRITE_3D:
+            return new Sprite3D(handle);
+        case TEXTURE_2D:
+            return new Texture2D(handle);
+        case VERTEX_ARRAY:
+            return new VertexArray(handle);
+        case VERTEX_BUFFER:
+            return new VertexBuffer(handle);
+        case WORLD:
+            return new World(handle);
+        default:
+            throw new Error();
+        }
+    }
+
+    /**
+     * Forces removal of an object from the handle-to-object map.
+     */
+    static final void deregister(Object3D obj, Interface self)
+    {
+        self.liveObjects.remove(new Integer(obj.handle));
+        if (self.liveObjects.isEmpty() && self.iShutdown)
+        {
+            self.registeredFinalize();
+        }
+    }
+
+    /**
+     * Forces removal of an object from the handle-to-object map.
+     */
+    static final void deregister(Loader obj, Interface self)
+    {
+        self.liveObjects.remove(new Integer(obj.handle));
+        if (self.liveObjects.isEmpty() && self.iShutdown)
+        {
+            self.registeredFinalize();
+        }
+    }
+
+    /**
+     *  Sets shutdown indication flag. Actual native
+     *  cleanup occurs when liveObjects count is zero
+     */
+    void signalShutdown()
+    {
+        iShutdown = true;
+    }
+
+    /**
+     * Gets the state of this interface
+     * @return true if interface is fully constructed, otherwise false
+     */
+    boolean isFullyInitialized()
+    {
+        return iNativeInitialized;
+    }
+
+    //------------------------------------------------------------------
+    // Private methods
+    //------------------------------------------------------------------
+
+    /**
+     * Checks the status of the native interface
+     */
+    private void integrityCheck()
+    {
+        if (!iNativeInitialized)
+        {
+            // If native interface cannot be initialized we cannot recover from it
+            if (!initNativePeer())
+            {
+                throw new Error("UI thread not available");
+            }
+        }
+    }
+
+    /**
+     * Initializes native peer
+     * @return true if native interface was succesfully inialized otherwise false
+     */
+    private boolean initNativePeer()
+    {
+        if (iNativeInitialized)
+        {
+            return true;
+        }
+        if (Platform.uiThreadAvailable())
+        {
+            Platform.executeInUIThread(
+                new M3gRunnable()
+            {
+                public void doRun()
+                {
+                    handle = _ctor();
+                }
+            });
+            iNativeInitialized = true;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+//#ifdef RD_JAVA_OMJ
+    private void doFinalize()
+    {
+        if (mFinalizer != null)
+        {
+            registeredFinalize();
+            mFinalizer = null;
+        }
+    }
+//#endif // RD_JAVA_OMJ
+
+    // Native finalization hook, for Symbian only
+    final private void registeredFinalize()
+    {
+        if (Interface.instance != null)
+        {
+            // Finalize M3G interface
+            Platform.executeInUIThread(
+                new M3gRunnable()
+            {
+                public void doRun()
+                {
+                    Platform.finalizeInterface(handle);
+                }
+            });
+            Interface.instance = null;
+        }
+    }
+
+    // Native constructor
+    private static native int _ctor();
+
+    // Native class ID resolver
+    private static native int _getClassID(int hObject);
+}