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
1936e612a488511940b61f09803b270aa1c61b68e0Jason Samsimport android.util.Log;
2036e612a488511940b61f09803b270aa1c61b68e0Jason Sams
2136e612a488511940b61f09803b270aa1c61b68e0Jason Sams/**
2206d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams * BaseObj is the base class for interfacing with native renderscript objects.
2306d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams * It primarly contains code for tracking the native object ID and forcably
2406d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams * disconecting the object from the native allocation for early cleanup.
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
4227676fe24be7444a174c15df476e49adc5335d03Jason Sams    /**
4327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * Lookup the native object ID for this object.  Primarily used by the
4427676fe24be7444a174c15df476e49adc5335d03Jason Sams     * generated reflected code.
4527676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
4627676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
4727676fe24be7444a174c15df476e49adc5335d03Jason Sams     * @return int
4827676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
49bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    int getID() {
507aa150c0967b725850cf27de58f50a25a960b092Jason Sams        if (mDestroyed) {
51c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("using a destroyed object.");
527aa150c0967b725850cf27de58f50a25a960b092Jason Sams        }
535476b450e50939940dcf3f15c92335cee2fc572dJason Sams        if (mID == 0) {
545476b450e50939940dcf3f15c92335cee2fc572dJason Sams            throw new RSRuntimeException("Internal error: Object id 0.");
555476b450e50939940dcf3f15c92335cee2fc572dJason Sams        }
5636e612a488511940b61f09803b270aa1c61b68e0Jason Sams        return mID;
5736e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
5836e612a488511940b61f09803b270aa1c61b68e0Jason Sams
59bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    void checkValid() {
60bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        if (mID == 0) {
61bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams            throw new RSIllegalArgumentException("Invalid object.");
62bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams        }
63bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams    }
64bf6ef8d78fffbce6c1849a4a28fb3f4401ad039eJason Sams
6506d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private int mID;
6606d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private boolean mDestroyed;
6706d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    private String mName;
6836e612a488511940b61f09803b270aa1c61b68e0Jason Sams    RenderScript mRS;
6936e612a488511940b61f09803b270aa1c61b68e0Jason Sams
7027676fe24be7444a174c15df476e49adc5335d03Jason Sams    /**
7127676fe24be7444a174c15df476e49adc5335d03Jason Sams     * setName assigns a name to an object.  This object can later be looked up
7227676fe24be7444a174c15df476e49adc5335d03Jason Sams     * by this name.  This name will also be retained if the object is written
7327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * to an A3D file.
7427676fe24be7444a174c15df476e49adc5335d03Jason Sams     *
7527676fe24be7444a174c15df476e49adc5335d03Jason Sams     * @param name The name to assign to the object.
7627676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
7727676fe24be7444a174c15df476e49adc5335d03Jason Sams    public void setName(String name) {
7884a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        if (name == null) {
7984a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8084a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName requires a string of non-zero length.");
8184a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines        }
8227676fe24be7444a174c15df476e49adc5335d03Jason Sams        if(name.length() < 1) {
8384a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8484a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName does not accept a zero length string.");
8536e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
8636e612a488511940b61f09803b270aa1c61b68e0Jason Sams        if(mName != null) {
8784a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines            throw new RSIllegalArgumentException(
8884a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines                "setName object already has a name.");
8936e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9036e612a488511940b61f09803b270aa1c61b68e0Jason Sams
9136e612a488511940b61f09803b270aa1c61b68e0Jason Sams        try {
9227676fe24be7444a174c15df476e49adc5335d03Jason Sams            byte[] bytes = name.getBytes("UTF-8");
9336e612a488511940b61f09803b270aa1c61b68e0Jason Sams            mRS.nAssignName(mID, bytes);
9427676fe24be7444a174c15df476e49adc5335d03Jason Sams            mName = name;
9536e612a488511940b61f09803b270aa1c61b68e0Jason Sams        } catch (java.io.UnsupportedEncodingException e) {
9636e612a488511940b61f09803b270aa1c61b68e0Jason Sams            throw new RuntimeException(e);
9736e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
9836e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
9936e612a488511940b61f09803b270aa1c61b68e0Jason Sams
1000400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    /**
1010400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     * @return name of the renderscript object
1020400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk     */
1030400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    public String getName() {
1040400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk        return mName;
1050400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk    }
1060400b07c6bfc3fca49bc10db0a2040aba8664c8eAlex Sakhartchouk
107c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams    protected void finalize() throws Throwable {
1081bada8cd6e4f340de93cff4a2439835fc3b1456cJason Sams        if (!mDestroyed) {
109a9e7a05b84470257637c97d65f6562aa832c66efJason Sams            if(mID != 0 && mRS.isAlive()) {
110d78be37d81f6c1aba75180c7608753a027a881eeJason Sams                mRS.nObjDestroy(mID);
111730ee65d4ddb307898053b623120bad1655fadadJason Sams            }
112a9e7a05b84470257637c97d65f6562aa832c66efJason Sams            mRS = null;
113730ee65d4ddb307898053b623120bad1655fadadJason Sams            mID = 0;
114730ee65d4ddb307898053b623120bad1655fadadJason Sams            mDestroyed = true;
1155235cf3f41cfcfe39c7072fddf1ead52db31292dJason Sams            //Log.v(RenderScript.LOG_TAG, getClass() +
1165235cf3f41cfcfe39c7072fddf1ead52db31292dJason Sams            // " auto finalizing object without having released the RS reference.");
11736e612a488511940b61f09803b270aa1c61b68e0Jason Sams        }
11836e612a488511940b61f09803b270aa1c61b68e0Jason Sams        super.finalize();
11936e612a488511940b61f09803b270aa1c61b68e0Jason Sams    }
1207ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
12127676fe24be7444a174c15df476e49adc5335d03Jason Sams    /**
12284a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines     * destroy disconnects the object from the native object effectively
12327676fe24be7444a174c15df476e49adc5335d03Jason Sams     * rendering this java object dead.  The primary use is to force immediate
12484a97cae1e53400676a4dfd6c7bf75f9ac230fceStephen Hines     * cleanup of resources when it is believed the GC will not respond quickly
12527676fe24be7444a174c15df476e49adc5335d03Jason Sams     * enough.
12627676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
12706d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams    synchronized public void destroy() {
1287ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        if(mDestroyed) {
129c1d6210fb5cc558ccea95a59a2b33bb9015fc7deJason Sams            throw new RSInvalidStateException("Object already destroyed.");
1307ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        }
1317ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        mDestroyed = true;
1327ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams        mRS.nObjDestroy(mID);
1337ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams    }
1347ce033d797e5df5e2131e2ed459fba181eaf4658Jason Sams
13527676fe24be7444a174c15df476e49adc5335d03Jason Sams    /**
13627676fe24be7444a174c15df476e49adc5335d03Jason Sams     * If an object came from an a3d file, java fields need to be
13727676fe24be7444a174c15df476e49adc5335d03Jason Sams     * created with objects from the native layer
13827676fe24be7444a174c15df476e49adc5335d03Jason Sams     */
13980a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    void updateFromNative() {
14006d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mRS.validate();
14106d69de78845659e6904ae4964e606a7f1a6a4a8Jason Sams        mName = mRS.nGetName(getID());
14280a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk    }
14380a4c2cd34aedb4f1a2e5e7d1ac26a9aeebe41aeAlex Sakhartchouk
144705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    /**
145705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Calculates the hash code value for a BaseObj.
146705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
147705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return int
148705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
149705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
150705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public int hashCode() {
151705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        return mID;
152705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
153705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
154705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    /**
155705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * Compare the current BaseObj with another BaseObj for equality.
156705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
157705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @param obj The object to check equality with.
158705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     *
159705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     * @return boolean
160705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines     */
161705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    @Override
162705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    public boolean equals(Object obj) {
163705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        // Early-out check to see if both BaseObjs are actually the same
164705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (this == obj)
165705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return true;
166705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
167705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        if (getClass() != obj.getClass()) {
168705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines            return false;
169705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        }
170705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines
171705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        BaseObj b = (BaseObj) obj;
172705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines        return mID == b.mID;
173705d2ea63a4b3c2345af83eec9dabdeea29cfa9fStephen Hines    }
17436e612a488511940b61f09803b270aa1c61b68e0Jason Sams}
17536e612a488511940b61f09803b270aa1c61b68e0Jason Sams
176