136e612a488511940b61f09803b270aa1c61b68e0Jason Sams/*
236e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Copyright (C) 2008 The Android Open Source Project
336e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
536e612a488511940b61f09803b270aa1c61b68e0Jason Sams * you may not use this file except in compliance with the License.
636e612a488511940b61f09803b270aa1c61b68e0Jason Sams * You may obtain a copy of the License at
736e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
836e612a488511940b61f09803b270aa1c61b68e0Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
936e612a488511940b61f09803b270aa1c61b68e0Jason Sams *
1036e612a488511940b61f09803b270aa1c61b68e0Jason Sams * Unless required by applicable law or agreed to in writing, software
1136e612a488511940b61f09803b270aa1c61b68e0Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
1236e612a488511940b61f09803b270aa1c61b68e0Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336e612a488511940b61f09803b270aa1c61b68e0Jason Sams * See the License for the specific language governing permissions and
1436e612a488511940b61f09803b270aa1c61b68e0Jason Sams * limitations under the License.
1536e612a488511940b61f09803b270aa1c61b68e0Jason Sams */
1636e612a488511940b61f09803b270aa1c61b68e0Jason Sams
1736e612a488511940b61f09803b270aa1c61b68e0Jason Samspackage android.renderscript;
1836e612a488511940b61f09803b270aa1c61b68e0Jason Sams
196484b6be5ca5233614d0a8991a5d909543824fc7Yang Niimport dalvik.system.CloseGuard;
20504abb362660f87239103be182a2e717a98ff32aTim Murrayimport java.util.concurrent.locks.ReentrantReadWriteLock;
2136e612a488511940b61f09803b270aa1c61b68e0Jason Sams
229c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines/**
23c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * BaseObj is the base class for all RenderScript objects owned by a RS context.
24c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * It is responsible for lifetime management and resource tracking. This class
25c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * should not be used by a user application.
2606d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams *
2736e612a488511940b61f09803b270aa1c61b68e0Jason Sams **/
28ef353dde086a6833471deff4da58a6eaf8a1ef36Stephen Hinespublic class BaseObj {
297a629fac82f88126642081b4474879f6a883e313Tim Murray    BaseObj(long id, RenderScript rs) {
30718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        rs.validate();
3136e612a488511940b61f09803b270aa1c61b68e0Jason Sams        mRS = rs;
320de9444aa6c25d2c586e8204a6168d10e67376e0Alex Sakhartchouk        mID = id;
331bada8cd6e4f340de93cff4a2439835fc3b1456cJason Sams        mDestroyed = false;
3436e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
3536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
360e0c0885aed99a119052a792becb5a0c5a93632dAshok Bhat    void setID(long id) {
3706d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        if (mID != 0) {
3806d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams            throw new RSRuntimeException("Internal Error, reset of object ID.");
3906d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        }
4006d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mID = id;
4106d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    }
4206d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams
439c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
4427676fe24be7444a174c15df476e49adc5335d03Jason Sams     * Lookup the native object ID for this object.  Primarily used by the
4527676fe24be7444a174c15df476e49adc5335d03Jason Sams     * generated reflected code.
4627676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
47e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams     * @param rs Context to verify against internal context for
48e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams     *           match.
4927676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
507a629fac82f88126642081b4474879f6a883e313Tim Murray     * @return long
5127676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
527a629fac82f88126642081b4474879f6a883e313Tim Murray    long getID(RenderScript rs) {
53e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        mRS.validate();
547aa150c0967b725850cf27de58f50a25a960b092Jason Sams        if (mDestroyed) {
55c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("using a destroyed object.");
567aa150c0967b725850cf27de58f50a25a960b092Jason Sams        }
575476b450e50939940dcf3f15c92335cee2fc572dJason Sams        if (mID == 0) {
585476b450e50939940dcf3f15c92335cee2fc572dJason Sams            throw new RSRuntimeException("Internal error: Object id 0.");
595476b450e50939940dcf3f15c92335cee2fc572dJason Sams        }
60e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        if ((rs != null) && (rs != mRS)) {
61e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams            throw new RSInvalidStateException("using object with mismatched context.");
62e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        }
6336e612a488511940b61f09803b270aa1c61b68e0Jason Sams        return mID;
6436e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
6536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
66bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    void checkValid() {
67bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        if (mID == 0) {
68bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams            throw new RSIllegalArgumentException("Invalid object.");
69bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        }
70bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    }
71bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams
727a629fac82f88126642081b4474879f6a883e313Tim Murray    private long mID;
736484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni    final CloseGuard guard = CloseGuard.get();
7406d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private boolean mDestroyed;
7506d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private String mName;
7636e612a488511940b61f09803b270aa1c61b68e0Jason Sams    RenderScript mRS;
7736e612a488511940b61f09803b270aa1c61b68e0Jason Sams
789c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
7927676fe24be7444a174c15df476e49adc5335d03Jason Sams     * setName assigns a name to an object.  This object can later be looked up
80c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * by this name.
8127676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
8227676fe24be7444a174c15df476e49adc5335d03Jason Sams     * @param name The name to assign to the object.
8327676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
8427676fe24be7444a174c15df476e49adc5335d03Jason Sams    public void setName(String name) {
8584a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        if (name == null) {
8684a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8784a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName requires a string of non-zero length.");
8884a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        }
8927676fe24be7444a174c15df476e49adc5335d03Jason Sams        if(name.length() < 1) {
9084a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
9184a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName does not accept a zero length string.");
9236e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9336e612a488511940b61f09803b270aa1c61b68e0Jason Sams        if(mName != null) {
9484a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
9584a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName object already has a name.");
9636e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9736e612a488511940b61f09803b270aa1c61b68e0Jason Sams
9836e612a488511940b61f09803b270aa1c61b68e0Jason Sams        try {
9927676fe24be7444a174c15df476e49adc5335d03Jason Sams            byte[] bytes = name.getBytes("UTF-8");
10036e612a488511940b61f09803b270aa1c61b68e0Jason Sams            mRS.nAssignName(mID, bytes);
10127676fe24be7444a174c15df476e49adc5335d03Jason Sams            mName = name;
10236e612a488511940b61f09803b270aa1c61b68e0Jason Sams        } catch (java.io.UnsupportedEncodingException e) {
10336e612a488511940b61f09803b270aa1c61b68e0Jason Sams            throw new RuntimeException(e);
10436e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
10536e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
10636e612a488511940b61f09803b270aa1c61b68e0Jason Sams
1079c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
1080400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     * @return name of the renderscript object
1090400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     */
1100400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    public String getName() {
1110400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk        return mName;
1120400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    }
1130400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk
114504abb362660f87239103be182a2e717a98ff32aTim Murray    private void helpDestroy() {
115504abb362660f87239103be182a2e717a98ff32aTim Murray        boolean shouldDestroy = false;
116504abb362660f87239103be182a2e717a98ff32aTim Murray        synchronized(this) {
117504abb362660f87239103be182a2e717a98ff32aTim Murray            if (!mDestroyed) {
118504abb362660f87239103be182a2e717a98ff32aTim Murray                shouldDestroy = true;
119504abb362660f87239103be182a2e717a98ff32aTim Murray                mDestroyed = true;
120504abb362660f87239103be182a2e717a98ff32aTim Murray            }
121504abb362660f87239103be182a2e717a98ff32aTim Murray        }
122504abb362660f87239103be182a2e717a98ff32aTim Murray
123504abb362660f87239103be182a2e717a98ff32aTim Murray        if (shouldDestroy) {
1246484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni            guard.close();
125504abb362660f87239103be182a2e717a98ff32aTim Murray            // must include nObjDestroy in the critical section
126504abb362660f87239103be182a2e717a98ff32aTim Murray            ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
127504abb362660f87239103be182a2e717a98ff32aTim Murray            rlock.lock();
1286d63c84f443b2dcc573cac69f234b3d52493d7b1Tim Murray            // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
1296d63c84f443b2dcc573cac69f234b3d52493d7b1Tim Murray            if(mRS.isAlive() && mID != 0) {
130d78be37d81f6c1aba75180c7608753a027a881eeJason Sams                mRS.nObjDestroy(mID);
131730ee65d4ddb307898053b623120bad1655fadadJason Sams            }
132504abb362660f87239103be182a2e717a98ff32aTim Murray            rlock.unlock();
133a9e7a05b84470257637c97d65f6562aa832c66efJason Sams            mRS = null;
134730ee65d4ddb307898053b623120bad1655fadadJason Sams            mID = 0;
13536e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
136504abb362660f87239103be182a2e717a98ff32aTim Murray    }
137504abb362660f87239103be182a2e717a98ff32aTim Murray
138504abb362660f87239103be182a2e717a98ff32aTim Murray    protected void finalize() throws Throwable {
1396484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni        try {
1406484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni            if (guard != null) {
1416484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni                guard.warnIfOpen();
1426484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni            }
1436484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni            helpDestroy();
1446484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni        } finally {
1456484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni            super.finalize();
1466484b6be5ca5233614d0a8991a5d909543824fc7Yang Ni        }
14736e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
1487ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
1499c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
150c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Frees any native resources associated with this object.  The
151c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * primary use is to force immediate cleanup of resources when it is
152c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * believed the GC will not respond quickly enough.
15327676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
154504abb362660f87239103be182a2e717a98ff32aTim Murray    public void destroy() {
1557ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        if(mDestroyed) {
156c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("Object already destroyed.");
1577ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        }
158504abb362660f87239103be182a2e717a98ff32aTim Murray        helpDestroy();
1597ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams    }
1607ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
1619c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
16227676fe24be7444a174c15df476e49adc5335d03Jason Sams     * If an object came from an a3d file, java fields need to be
16327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * created with objects from the native layer
16427676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
16580a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    void updateFromNative() {
16606d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mRS.validate();
167e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        mName = mRS.nGetName(getID(mRS));
16880a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    }
16980a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk
1709c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
171705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Calculates the hash code value for a BaseObj.
172705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
173705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return int
174705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
175705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
176705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public int hashCode() {
1777a629fac82f88126642081b4474879f6a883e313Tim Murray        return (int)((mID & 0xfffffff) ^ (mID >> 32));
178705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
179705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
1809c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
181705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Compare the current BaseObj with another BaseObj for equality.
182705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
183705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @param obj The object to check equality with.
184705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
185705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return boolean
186705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
187705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
188705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public boolean equals(Object obj) {
189705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        // Early-out check to see if both BaseObjs are actually the same
190705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (this == obj)
191705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return true;
192705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
19378214c9531f936549bd9141ca7a6aa5ac27c8622Tim Murray        if (obj == null) {
19478214c9531f936549bd9141ca7a6aa5ac27c8622Tim Murray            return false;
19578214c9531f936549bd9141ca7a6aa5ac27c8622Tim Murray        }
19678214c9531f936549bd9141ca7a6aa5ac27c8622Tim Murray
197705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (getClass() != obj.getClass()) {
198705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return false;
199705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        }
200705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
201705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        BaseObj b = (BaseObj) obj;
202705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        return mID == b.mID;
203705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
20436e612a488511940b61f09803b270aa1c61b68e0Jason Sams}
20536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
206