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
19ff7256e757502279b1777127a12eba235be679aeJason Samsimport java.util.concurrent.locks.ReentrantReadWriteLock;
2036e612a488511940b61f09803b270aa1c61b68e0Jason Sams
219c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines/**
22c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * BaseObj is the base class for all RenderScript objects owned by a RS context.
23c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * It is responsible for lifetime management and resource tracking. This class
24c11e25c4e653124def1fb18e203b894f42106cbeTim Murray * should not be used by a user application.
2506d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams *
2636e612a488511940b61f09803b270aa1c61b68e0Jason Sams **/
27ef353dde086a6833471deff4da58a6eaf8a1ef36Stephen Hinespublic class BaseObj {
280de9444aa6c25d2c586e8204a6168d10e67376e0Alex Sakhartchouk    BaseObj(int id, RenderScript rs) {
29718cd1f322ee5b62b6a49cb36195bcb18a5ab711Jason Sams        rs.validate();
3036e612a488511940b61f09803b270aa1c61b68e0Jason Sams        mRS = rs;
310de9444aa6c25d2c586e8204a6168d10e67376e0Alex Sakhartchouk        mID = id;
321bada8cd6e4f340de93cff4a2439835fc3b1456cJason Sams        mDestroyed = false;
3336e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
3436e612a488511940b61f09803b270aa1c61b68e0Jason Sams
3506d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    void setID(int id) {
3606d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        if (mID != 0) {
3706d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams            throw new RSRuntimeException("Internal Error, reset of object ID.");
3806d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        }
3906d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mID = id;
4006d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    }
4106d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams
429c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
4327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * Lookup the native object ID for this object.  Primarily used by the
4427676fe24be7444a174c15df476e49adc5335d03Jason Sams     * generated reflected code.
4527676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
46e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams     * @param rs Context to verify against internal context for
47e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams     *           match.
4827676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
4927676fe24be7444a174c15df476e49adc5335d03Jason Sams     * @return int
5027676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
51e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams    int getID(RenderScript rs) {
52e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        mRS.validate();
537aa150c0967b725850cf27de58f50a25a960b092Jason Sams        if (mDestroyed) {
54c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("using a destroyed object.");
557aa150c0967b725850cf27de58f50a25a960b092Jason Sams        }
565476b450e50939940dcf3f15c92335cee2fc572dJason Sams        if (mID == 0) {
575476b450e50939940dcf3f15c92335cee2fc572dJason Sams            throw new RSRuntimeException("Internal error: Object id 0.");
585476b450e50939940dcf3f15c92335cee2fc572dJason Sams        }
59e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        if ((rs != null) && (rs != mRS)) {
60e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams            throw new RSInvalidStateException("using object with mismatched context.");
61e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        }
6236e612a488511940b61f09803b270aa1c61b68e0Jason Sams        return mID;
6336e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
6436e612a488511940b61f09803b270aa1c61b68e0Jason Sams
65bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    void checkValid() {
66bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        if (mID == 0) {
67bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams            throw new RSIllegalArgumentException("Invalid object.");
68bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        }
69bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    }
70bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams
7106d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private int mID;
7206d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private boolean mDestroyed;
7306d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private String mName;
7436e612a488511940b61f09803b270aa1c61b68e0Jason Sams    RenderScript mRS;
7536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
769c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
7727676fe24be7444a174c15df476e49adc5335d03Jason Sams     * setName assigns a name to an object.  This object can later be looked up
78c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * by this name.
7927676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
8027676fe24be7444a174c15df476e49adc5335d03Jason Sams     * @param name The name to assign to the object.
8127676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
8227676fe24be7444a174c15df476e49adc5335d03Jason Sams    public void setName(String name) {
8384a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        if (name == null) {
8484a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8584a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName requires a string of non-zero length.");
8684a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        }
8727676fe24be7444a174c15df476e49adc5335d03Jason Sams        if(name.length() < 1) {
8884a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8984a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName does not accept a zero length string.");
9036e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9136e612a488511940b61f09803b270aa1c61b68e0Jason Sams        if(mName != null) {
9284a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
9384a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName object already has a name.");
9436e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
9636e612a488511940b61f09803b270aa1c61b68e0Jason Sams        try {
9727676fe24be7444a174c15df476e49adc5335d03Jason Sams            byte[] bytes = name.getBytes("UTF-8");
9836e612a488511940b61f09803b270aa1c61b68e0Jason Sams            mRS.nAssignName(mID, bytes);
9927676fe24be7444a174c15df476e49adc5335d03Jason Sams            mName = name;
10036e612a488511940b61f09803b270aa1c61b68e0Jason Sams        } catch (java.io.UnsupportedEncodingException e) {
10136e612a488511940b61f09803b270aa1c61b68e0Jason Sams            throw new RuntimeException(e);
10236e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
10336e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
10436e612a488511940b61f09803b270aa1c61b68e0Jason Sams
1059c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
1060400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     * @return name of the renderscript object
1070400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     */
1080400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    public String getName() {
1090400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk        return mName;
1100400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    }
1110400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk
112ff7256e757502279b1777127a12eba235be679aeJason Sams    private void helpDestroy() {
113ff7256e757502279b1777127a12eba235be679aeJason Sams        boolean shouldDestroy = false;
114ff7256e757502279b1777127a12eba235be679aeJason Sams        synchronized(this) {
115ff7256e757502279b1777127a12eba235be679aeJason Sams            if (!mDestroyed) {
116ff7256e757502279b1777127a12eba235be679aeJason Sams                shouldDestroy = true;
117ff7256e757502279b1777127a12eba235be679aeJason Sams                mDestroyed = true;
118ff7256e757502279b1777127a12eba235be679aeJason Sams            }
119ff7256e757502279b1777127a12eba235be679aeJason Sams        }
120ff7256e757502279b1777127a12eba235be679aeJason Sams
121ff7256e757502279b1777127a12eba235be679aeJason Sams        if (shouldDestroy) {
122ff7256e757502279b1777127a12eba235be679aeJason Sams            // must include nObjDestroy in the critical section
123ff7256e757502279b1777127a12eba235be679aeJason Sams            ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
124ff7256e757502279b1777127a12eba235be679aeJason Sams            rlock.lock();
125cf8573c15456c4581b691c7380722ea6dccf11c5Jason Sams            // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
126cf8573c15456c4581b691c7380722ea6dccf11c5Jason Sams            if(mRS.isAlive() && mID != 0) {
127d78be37d81f6c1aba75180c7608753a027a881eeJason Sams                mRS.nObjDestroy(mID);
128730ee65d4ddb307898053b623120bad1655fadadJason Sams            }
129ff7256e757502279b1777127a12eba235be679aeJason Sams            rlock.unlock();
130a9e7a05b84470257637c97d65f6562aa832c66efJason Sams            mRS = null;
131730ee65d4ddb307898053b623120bad1655fadadJason Sams            mID = 0;
13236e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
133ff7256e757502279b1777127a12eba235be679aeJason Sams    }
134ff7256e757502279b1777127a12eba235be679aeJason Sams
135ff7256e757502279b1777127a12eba235be679aeJason Sams    protected void finalize() throws Throwable {
136ff7256e757502279b1777127a12eba235be679aeJason Sams        helpDestroy();
13736e612a488511940b61f09803b270aa1c61b68e0Jason Sams        super.finalize();
13836e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
1397ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
1409c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
141c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * Frees any native resources associated with this object.  The
142c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * primary use is to force immediate cleanup of resources when it is
143c11e25c4e653124def1fb18e203b894f42106cbeTim Murray     * believed the GC will not respond quickly enough.
14427676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
145ff7256e757502279b1777127a12eba235be679aeJason Sams    public void destroy() {
1467ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        if(mDestroyed) {
147c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("Object already destroyed.");
1487ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        }
149ff7256e757502279b1777127a12eba235be679aeJason Sams        helpDestroy();
1507ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams    }
1517ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
1529c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
15327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * If an object came from an a3d file, java fields need to be
15427676fe24be7444a174c15df476e49adc5335d03Jason Sams     * created with objects from the native layer
15527676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
15680a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    void updateFromNative() {
15706d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mRS.validate();
158e07694b24f7d12d72b084b6651356681ebd0efd6Jason Sams        mName = mRS.nGetName(getID(mRS));
15980a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    }
16080a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk
1619c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
162705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Calculates the hash code value for a BaseObj.
163705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
164705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return int
165705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
166705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
167705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public int hashCode() {
168705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        return mID;
169705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
170705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
1719c9ad3f8c218954e46aab81f9af7834cea5675caStephen Hines    /**
172705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Compare the current BaseObj with another BaseObj for equality.
173705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
174705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @param obj The object to check equality with.
175705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
176705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return boolean
177705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
178705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
179705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public boolean equals(Object obj) {
180705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        // Early-out check to see if both BaseObjs are actually the same
181705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (this == obj)
182705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return true;
183705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
184705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (getClass() != obj.getClass()) {
185705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return false;
186705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        }
187705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
188705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        BaseObj b = (BaseObj) obj;
189705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        return mID == b.mID;
190705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
19136e612a488511940b61f09803b270aa1c61b68e0Jason Sams}
19236e612a488511940b61f09803b270aa1c61b68e0Jason Sams
193