javauis/m3g_qt/javasrc/javax/microedition/m3g/Interface.java
branchRCL_3
changeset 19 04becd199f91
child 40 c6043ea9b06a
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 package javax.microedition.m3g;
       
    19 
       
    20 import java.lang.ref.WeakReference;
       
    21 import java.util.Hashtable;
       
    22 import org.eclipse.swt.widgets.Display;
       
    23 #ifdef RD_JAVA_OMJ
       
    24 import com.nokia.mj.impl.rt.support.Finalizer;
       
    25 #endif // RD_JAVA_OMJ
       
    26 
       
    27 /**
       
    28  * M3G interface object. An interface is automatically created for
       
    29  * each MIDlet using the 3D API to keep track of Java-side object
       
    30  * lifetimes etc.
       
    31  */
       
    32 class Interface
       
    33 {
       
    34     //------------------------------------------------------------------
       
    35     // Static data
       
    36     //------------------------------------------------------------------
       
    37 
       
    38     // Common class enumeration for Java and native code
       
    39 
       
    40     private static final int ANIMATION_CONTROLLER = 0x01;
       
    41     private static final int ANIMATION_TRACK      = 0x02;
       
    42     private static final int APPEARANCE           = 0x03;
       
    43     private static final int BACKGROUND           = 0x04;
       
    44     private static final int CAMERA               = 0x05;
       
    45     private static final int COMPOSITING_MODE     = 0x06;
       
    46     private static final int FOG                  = 0x07;
       
    47     private static final int GROUP                = 0x08;
       
    48     private static final int IMAGE_2D             = 0x09;
       
    49     private static final int INDEX_BUFFER         = 0x0A;
       
    50     private static final int KEYFRAME_SEQUENCE    = 0x0B;
       
    51     private static final int LIGHT                = 0x0C;
       
    52     private static final int LOADER               = 0x0D;
       
    53     private static final int MATERIAL             = 0x0E;
       
    54     private static final int MESH                 = 0x0F;
       
    55     private static final int MORPHING_MESH        = 0x10;
       
    56     private static final int POLYGON_MODE         = 0x11;
       
    57     private static final int RENDER_CONTEXT       = 0x12;
       
    58     private static final int SKINNED_MESH         = 0x13;
       
    59     private static final int SPRITE_3D            = 0x14;
       
    60     private static final int TEXTURE_2D           = 0x15;
       
    61     private static final int VERTEX_ARRAY         = 0x16;
       
    62     private static final int VERTEX_BUFFER        = 0x17;
       
    63     private static final int WORLD                = 0x18;
       
    64 
       
    65     // Once created, the interface singleton currently remains in
       
    66     // memory until VM exit.  By using a WeakReference here, with hard
       
    67     // references stored in each object, it could be GC'd when no more
       
    68     // objects exist, but that probably isn't worth the extra memory
       
    69     // overhead.
       
    70 
       
    71     //private static Hashtable s_instances = new Hashtable();
       
    72     private static Interface instance = null;
       
    73 
       
    74     //------------------------------------------------------------------
       
    75     // Instance data
       
    76     //------------------------------------------------------------------
       
    77 
       
    78     /**
       
    79      * Handle of the native interface object.
       
    80      */
       
    81     private int handle;
       
    82 
       
    83     /**
       
    84      * Global handle-to-Object3D map used to both find the Java
       
    85      * counterparts of objects returned from the native methods, and
       
    86      * keep certain objects from being garbage collected.
       
    87      */
       
    88     private final Hashtable liveObjects = new Hashtable();
       
    89 
       
    90     /**
       
    91      * Flag for shutdown signal
       
    92      */
       
    93     private boolean iShutdown = false;
       
    94 
       
    95     /**
       
    96      * Flag for native peer init state
       
    97      */
       
    98     private boolean iNativeInitialized = false;
       
    99 
       
   100 
       
   101 #ifdef RD_JAVA_OMJ
       
   102     private Finalizer mFinalizer;
       
   103 #endif // RD_JAVA_OMJ
       
   104 
       
   105     //------------------------------------------------------------------
       
   106     // Constructors
       
   107     //------------------------------------------------------------------
       
   108 
       
   109     private Interface()
       
   110     {
       
   111 
       
   112         // Contruct native peer
       
   113         initNativePeer();
       
   114 
       
   115 #ifdef RD_JAVA_OMJ
       
   116         mFinalizer = new Finalizer()
       
   117         {
       
   118             public void finalizeImpl()
       
   119             {
       
   120                 doFinalize();
       
   121             }
       
   122         };
       
   123 #else // RD_JAVA_OMJ
       
   124         Platform.registerFinalizer(this);
       
   125 #endif // RD_JAVA_OMJ
       
   126     }
       
   127 
       
   128     //------------------------------------------------------------------
       
   129     // Package methods
       
   130     //------------------------------------------------------------------
       
   131 
       
   132     /**
       
   133      * Returns the M3G interface instance for the current MIDlet.
       
   134      */
       
   135     static final Interface getInstance()
       
   136     {
       
   137         if (instance == null)
       
   138         {
       
   139             instance = new Interface();
       
   140         }
       
   141         return instance;
       
   142     }
       
   143 
       
   144     /**
       
   145      * Returns the native handle of the current Interface instance.
       
   146      */
       
   147     static final int getHandle()
       
   148     {
       
   149         getInstance().integrityCheck();
       
   150         return getInstance().handle;
       
   151     }
       
   152 
       
   153     /**
       
   154      * Registers an Object3D with this interface. The object is added
       
   155      * to the global handle-to-object map, and the native finalization
       
   156      * callback is set up. The handle of the object must already be
       
   157      * set at this point!
       
   158      */
       
   159     static final void register(Object3D obj)
       
   160     {
       
   161         Platform.registerFinalizer(obj);
       
   162         getInstance().liveObjects.put(new Integer(obj.handle),
       
   163                                       new WeakReference(obj));
       
   164     }
       
   165 
       
   166     static final void register(Loader obj)
       
   167     {
       
   168         Platform.registerFinalizer(obj);
       
   169         getInstance().liveObjects.put(new Integer(obj.handle),
       
   170                                       new WeakReference(obj));
       
   171     }
       
   172 
       
   173     /**
       
   174      * Finds an Object3D in the global handle-to-object map. Also
       
   175      * removes dead objects (that is, null references) from the map
       
   176      * upon encountering them.
       
   177      */
       
   178     static final Object3D findObject(int handle)
       
   179     {
       
   180         Interface self = getInstance();
       
   181         Integer iHandle = new Integer(handle);
       
   182         Object ref = self.liveObjects.get(iHandle);
       
   183 
       
   184         if (ref != null)
       
   185         {
       
   186             Object3D obj = (Object3D)((WeakReference)ref).get();
       
   187             if (obj == null)
       
   188             {
       
   189                 self.liveObjects.remove(iHandle);
       
   190             }
       
   191             return obj;
       
   192         }
       
   193         else
       
   194         {
       
   195             return null;
       
   196         }
       
   197     }
       
   198 
       
   199     /**
       
   200      * Returns the Java object representing a native object, or
       
   201      * creates a new proxy/peer if one doesn't exist yet.
       
   202      */
       
   203     static final Object3D getObjectInstance(int handle)
       
   204     {
       
   205 
       
   206         // A zero handle equals null
       
   207 
       
   208         if (handle == 0)
       
   209         {
       
   210             return null;
       
   211         }
       
   212 
       
   213         // Then try to find an existing Java representative for the
       
   214         // object
       
   215 
       
   216         Object3D obj = findObject(handle);
       
   217         if (obj != null)
       
   218         {
       
   219             return obj;
       
   220         }
       
   221 
       
   222         // Not found, create a new Java object. Note that only
       
   223         // non-abstract classes can possibly be returned.
       
   224 
       
   225         switch (_getClassID(handle))
       
   226         {
       
   227         case ANIMATION_CONTROLLER:
       
   228             return new AnimationController(handle);
       
   229         case ANIMATION_TRACK:
       
   230             return new AnimationTrack(handle);
       
   231         case APPEARANCE:
       
   232             return new Appearance(handle);
       
   233         case BACKGROUND:
       
   234             return new Background(handle);
       
   235         case CAMERA:
       
   236             return new Camera(handle);
       
   237         case COMPOSITING_MODE:
       
   238             return new CompositingMode(handle);
       
   239         case FOG:
       
   240             return new Fog(handle);
       
   241         case GROUP:
       
   242             return new Group(handle);
       
   243         case IMAGE_2D:
       
   244             return new Image2D(handle);
       
   245         case INDEX_BUFFER:
       
   246             return new TriangleStripArray(handle);
       
   247         case KEYFRAME_SEQUENCE:
       
   248             return new KeyframeSequence(handle);
       
   249         case LIGHT:
       
   250             return new Light(handle);
       
   251             //case LOADER:
       
   252         case MATERIAL:
       
   253             return new Material(handle);
       
   254         case MESH:
       
   255             return new Mesh(handle);
       
   256         case MORPHING_MESH:
       
   257             return new MorphingMesh(handle);
       
   258         case POLYGON_MODE:
       
   259             return new PolygonMode(handle);
       
   260             //case RENDER_CONTEXT:
       
   261         case SKINNED_MESH:
       
   262             return new SkinnedMesh(handle);
       
   263         case SPRITE_3D:
       
   264             return new Sprite3D(handle);
       
   265         case TEXTURE_2D:
       
   266             return new Texture2D(handle);
       
   267         case VERTEX_ARRAY:
       
   268             return new VertexArray(handle);
       
   269         case VERTEX_BUFFER:
       
   270             return new VertexBuffer(handle);
       
   271         case WORLD:
       
   272             return new World(handle);
       
   273         default:
       
   274             throw new Error();
       
   275         }
       
   276     }
       
   277 
       
   278     /**
       
   279      * Forces removal of an object from the handle-to-object map.
       
   280      */
       
   281     static final void deregister(Object3D obj, Interface self)
       
   282     {
       
   283         self.liveObjects.remove(new Integer(obj.handle));
       
   284         if (self.liveObjects.isEmpty() && self.iShutdown)
       
   285         {
       
   286             self.registeredFinalize();
       
   287         }
       
   288     }
       
   289 
       
   290     /**
       
   291      * Forces removal of an object from the handle-to-object map.
       
   292      */
       
   293     static final void deregister(Loader obj, Interface self)
       
   294     {
       
   295         self.liveObjects.remove(new Integer(obj.handle));
       
   296         if (self.liveObjects.isEmpty() && self.iShutdown)
       
   297         {
       
   298             self.registeredFinalize();
       
   299         }
       
   300     }
       
   301 
       
   302     /**
       
   303      *  Sets shutdown indication flag. Actual native
       
   304      *  cleanup occurs when liveObjects count is zero
       
   305      */
       
   306     void signalShutdown()
       
   307     {
       
   308         iShutdown = true;
       
   309     }
       
   310 
       
   311     /**
       
   312      * Gets the state of this interface
       
   313      * @return true if interface is fully constructed, otherwise false
       
   314      */
       
   315     boolean isFullyInitialized()
       
   316     {
       
   317         return iNativeInitialized;
       
   318     }
       
   319 
       
   320     //------------------------------------------------------------------
       
   321     // Private methods
       
   322     //------------------------------------------------------------------
       
   323 
       
   324     /**
       
   325      * Checks the status of the native interface
       
   326      */
       
   327     private void integrityCheck()
       
   328     {
       
   329         if (!iNativeInitialized)
       
   330         {
       
   331             // If native interface cannot be initialized we cannot recover from it
       
   332             if (!initNativePeer())
       
   333             {
       
   334                 throw new Error("UI thread not available");
       
   335             }
       
   336         }
       
   337     }
       
   338 
       
   339     /**
       
   340      * Initializes native peer
       
   341      * @return true if native interface was succesfully inialized otherwise false
       
   342      */
       
   343     private boolean initNativePeer()
       
   344     {
       
   345         if (iNativeInitialized)
       
   346         {
       
   347             return true;
       
   348         }
       
   349         if (Platform.uiThreadAvailable())
       
   350         {
       
   351             Platform.executeInUIThread(
       
   352                 new M3gRunnable()
       
   353             {
       
   354                 public void doRun()
       
   355                 {
       
   356                     handle = _ctor();
       
   357                 }
       
   358             });
       
   359             iNativeInitialized = true;
       
   360             return true;
       
   361         }
       
   362         else
       
   363         {
       
   364             return false;
       
   365         }
       
   366     }
       
   367 
       
   368 
       
   369 #ifdef RD_JAVA_OMJ
       
   370     private void doFinalize()
       
   371     {
       
   372         if (mFinalizer != null)
       
   373         {
       
   374             registeredFinalize();
       
   375             mFinalizer = null;
       
   376         }
       
   377     }
       
   378 #endif // RD_JAVA_OMJ
       
   379 
       
   380     // Native finalization hook, for Symbian only
       
   381     final private void registeredFinalize()
       
   382     {
       
   383         if (Interface.instance != null)
       
   384         {
       
   385             // Finalize M3G interface
       
   386             Platform.executeInUIThread(
       
   387                 new M3gRunnable()
       
   388             {
       
   389                 public void doRun()
       
   390                 {
       
   391                     Platform.finalizeInterface(handle);
       
   392                 }
       
   393             });
       
   394             Interface.instance = null;
       
   395         }
       
   396     }
       
   397 
       
   398     // Native constructor
       
   399     private static native int _ctor();
       
   400 
       
   401     // Native class ID resolver
       
   402     private static native int _getClassID(int hObject);
       
   403 }