1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * in compliance with the License. You may obtain a copy of the License at
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software distributed under the License
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * or implied. See the License for the specific language governing permissions and limitations under
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the License.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.annotation.TargetApi;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.Bitmap;
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Build;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.renderscript.Allocation;
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.renderscript.Element;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.renderscript.RenderScript;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.renderscript.Type;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.Log;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteOrder;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Arrays;
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Vector;
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksfinal class BackingStore {
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode None: Frame data will not be accessed at all. */
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_NONE = 0x00;
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode Bytes: Frame data will be accessed as a ByteBuffer. */
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_BYTES = 0x01;
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode Texture: Frame data will be accessed as a TextureSource. */
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_TEXTURE = 0x02;
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode RenderTarget: Frame data will be accessed as a RenderTarget. */
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_RENDERTARGET = 0x04;
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode Object: Frame data will be accessed as a generic Object. */
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_OBJECT = 0x08;
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode Bitmap: Frame data will be accessed as a Bitmap. */
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_BITMAP = 0x10;
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Access mode Allocation: Frame data will be accessed as a RenderScript Allocation. */
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static final int ACCESS_ALLOCATION = 0x20;
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int BACKING_BYTEBUFFER = 1;
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int BACKING_TEXTURE = 2;
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int BACKING_OBJECT = 3;
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int BACKING_BITMAP = 4;
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static final int BACKING_ALLOCATION = 5;
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private final FrameType mType;
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private int[] mDimensions;
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private long mTimestamp = Frame.TIMESTAMP_NOT_SET;
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private final FrameManager mFrameManager;
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Vector<Backing> mBackings = new Vector<Backing>();
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private boolean mWriteLocked = false;
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private int mReadLocks = 0;
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private int mRefCount = 1;
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The most up-to-date data backing */
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing mCurrentBacking = null;
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The currently locked backing */
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing mLockedBacking = null;
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Public Methods //////////////////////////////////////////////////////////////////////////////
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public BackingStore(FrameType type, int[] dimensions, FrameManager frameManager) {
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mType = type;
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mDimensions = dimensions != null ? Arrays.copyOf(dimensions, dimensions.length) : null;
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFrameManager = frameManager;
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public FrameType getFrameType() {
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mType;
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Object lockData(int mode, int accessFormat) {
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return lockBacking(mode, accessFormat).lock(accessFormat);
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Backing lockBacking(int mode, int access) {
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Backing backing = fetchBacking(mode, access);
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (backing == null) {
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Could not fetch frame data!");
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        lock(backing, mode);
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return backing;
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public boolean unlock() {
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mWriteLocked) {
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mWriteLocked = false;
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else if (mReadLocks > 0) {
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            --mReadLocks;
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mLockedBacking.unlock();
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mLockedBacking = null;
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return true;
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public BackingStore retain() {
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRefCount >= 10) {
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Log.w("BackingStore", "High ref-count of " + mRefCount + " on " + this + "!");
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRefCount <= 0) {
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("RETAINING RELEASED");
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ++mRefCount;
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return this;
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public BackingStore release() {
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRefCount <= 0) {
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("DOUBLE-RELEASE");
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        --mRefCount;
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRefCount == 0) {
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            releaseBackings();
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return null;
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return this;
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Resizes the backing store. This invalidates all data in the store.
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void resize(int[] newDimensions) {
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Vector<Backing> resized = new Vector<Backing>();
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (Backing backing : mBackings) {
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (backing.resize(newDimensions)) {
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                resized.add(backing);
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                releaseBacking(backing);
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackings = resized;
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mDimensions = newDimensions;
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public int[] getDimensions() {
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mDimensions;
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public int getElementCount() {
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int result = 1;
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mDimensions != null) {
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int dim : mDimensions) {
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                result *= dim;
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return result;
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void importStore(BackingStore store) {
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // TODO: Better backing selection?
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (store.mBackings.size() > 0) {
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            importBacking(store.mBackings.firstElement());
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mTimestamp = store.mTimestamp;
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the timestamp
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public long getTimestamp() {
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mTimestamp;
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param timestamp the timestamp to set
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setTimestamp(long timestamp) {
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mTimestamp = timestamp;
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Internal Methods ////////////////////////////////////////////////////////////////////////////
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing fetchBacking(int mode, int access) {
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Backing backing = getBacking(mode, access);
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (backing == null) {
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing = attachNewBacking(mode, access);
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        syncBacking(backing);
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return backing;
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void syncBacking(Backing backing) {
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (backing != null && backing.isDirty() && mCurrentBacking != null) {
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.syncTo(mCurrentBacking);
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing getBacking(int mode, int access) {
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // [Non-iterator looping]
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (int i = 0; i < mBackings.size(); ++i) {
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            final Backing backing = mBackings.get(i);
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int backingAccess =
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    (mode == Frame.MODE_WRITE) ? backing.writeAccess() : backing.readAccess();
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((backingAccess & access) == access) {
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                return backing;
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return null;
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing attachNewBacking(int mode, int access) {
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Backing backing = createBacking(mode, access);
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mBackings.size() > 0) {
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.markDirty();
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackings.add(backing);
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return backing;
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Backing createBacking(int mode, int access) {
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // TODO: If the read/write access flags indicate, make/fetch a GraphicBuffer backing.
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Backing backing = null;
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int elemSize = mType.getElementSize();
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (shouldFetchCached(access)) {
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing = mFrameManager.fetchBacking(mode, access, mDimensions, elemSize);
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (backing == null) {
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            switch (access) {
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_BYTES:
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing = new ByteBufferBacking();
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_TEXTURE:
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_RENDERTARGET:
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing = new TextureBacking();
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_OBJECT:
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing = new ObjectBacking();
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_BITMAP:
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing = new BitmapBacking();
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_ALLOCATION:
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    if (!AllocationBacking.isSupported()) {
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        throw new RuntimeException(
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                "Attempted to create an AllocationBacking in context that does " +
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                                "not support RenderScript!");
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    }
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing = new AllocationBacking(mFrameManager.getContext().getRenderScript());
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (backing == null) {
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Could not create backing for access type " + access + "!");
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (backing.requiresGpu() && !mFrameManager.getRunner().isOpenGLSupported()) {
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Cannot create backing that requires GPU in a runner that does not " +
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "support OpenGL!");
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.setDimensions(mDimensions);
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.setElementSize(elemSize);
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.setElementId(mType.getElementId());
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.allocate(mType);
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFrameManager.onBackingCreated(backing);
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return backing;
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void importBacking(Backing backing) {
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // TODO: This actually needs synchronization between the two BackingStore threads for the
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // general case
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int access = backing.requiresGpu() ? ACCESS_BYTES : backing.readAccess();
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        Backing newBacking = createBacking(Frame.MODE_READ, access);
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        newBacking.syncTo(backing);
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackings.add(newBacking);
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCurrentBacking = newBacking;
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void releaseBackings() {
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // [Non-iterator looping]
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (int i = 0; i < mBackings.size(); ++i) {
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            releaseBacking(mBackings.get(i));
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackings.clear();
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCurrentBacking = null;
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void releaseBacking(Backing backing) {
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFrameManager.onBackingAvailable(backing);
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void lock(Backing backingToLock, int mode) {
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mode == Frame.MODE_WRITE) {
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Make sure frame is not read-locked
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mReadLocks > 0) {
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Attempting to write-lock the read-locked frame " + this + "!");
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (mWriteLocked) {
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Attempting to write-lock the write-locked frame " + this + "!");
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Mark all other backings dirty
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // [Non-iterator looping]
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int i = 0; i < mBackings.size(); ++i) {
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                final Backing backing = mBackings.get(i);
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (backing != backingToLock) {
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing.markDirty();
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mWriteLocked = true;
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCurrentBacking = backingToLock;
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        } else {
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mWriteLocked) {
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Attempting to read-lock locked frame " + this + "!");
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ++mReadLocks;
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mLockedBacking = backingToLock;
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static boolean shouldFetchCached(int access) {
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return access != ACCESS_OBJECT;
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Backings ////////////////////////////////////////////////////////////////////////////////////
331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static abstract class Backing {
332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected int[] mDimensions = null;
333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private int mElementSize;
334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private int mElementID;
335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected boolean mIsDirty = false;
336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        int cachePriority = 0;
338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract void allocate(FrameType frameType);
340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract int readAccess();
342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract int writeAccess();
344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract void syncTo(Backing backing);
346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract Object lock(int accessType);
348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract int getType();
350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract boolean shouldCache();
352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract boolean requiresGpu();
354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract void destroy();
356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract int getSize();
358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void unlock() {
360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Default implementation does nothing.
361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setData(Object data) {
364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new RuntimeException("Internal error: Setting data on frame backing " + this
365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + ", which does not support setting data directly!");
366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setDimensions(int[] dimensions) {
369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mDimensions = dimensions;
370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setElementSize(int elemSize) {
373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mElementSize = elemSize;
374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setElementId(int elemId) {
377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mElementID = elemId;
378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int[] getDimensions() {
381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mDimensions;
382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getElementSize() {
385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mElementSize;
386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getElementId() {
389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mElementID;
390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean resize(int[] newDimensions) {
393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void markDirty() {
397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = true;
398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean isDirty() {
401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mIsDirty;
402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected void assertImageCompatible(FrameType type) {
405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (type.getElementId() != FrameType.ELEMENT_RGBA8888) {
406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot allocate texture with non-RGBA data type!");
407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (mDimensions == null || mDimensions.length != 2) {
408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot allocate non 2-dimensional texture!");
409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class ObjectBacking extends Backing {
415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Object mObject = null;
417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void allocate(FrameType frameType) {
420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mObject = null;
421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int readAccess() {
425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_OBJECT;
426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int writeAccess() {
430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_OBJECT;
431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void syncTo(Backing backing) {
435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            switch (backing.getType()) {
436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case BACKING_OBJECT:
437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mObject = backing.lock(ACCESS_OBJECT);
438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing.unlock();
439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case BACKING_BITMAP:
441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mObject = backing.lock(ACCESS_BITMAP);
442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    backing.unlock();
443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                default:
445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mObject = null;
446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = false;
448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Object lock(int accessType) {
452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mObject;
453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getType() {
457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return BACKING_OBJECT;
458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean shouldCache() {
462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requiresGpu() {
467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void destroy() {
472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mObject = null;
473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return 0;
478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setData(Object data) {
482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mObject = data;
483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class BitmapBacking extends Backing {
488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Bitmap mBitmap = null;
490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void allocate(FrameType frameType) {
493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            assertImageCompatible(frameType);
494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int readAccess() {
498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_BITMAP;
499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int writeAccess() {
503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_BITMAP;
504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void syncTo(Backing backing) {
508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int access = backing.readAccess();
509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((access & ACCESS_BITMAP) != 0) {
510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBitmap = (Bitmap) backing.lock(ACCESS_BITMAP);
511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BYTES) != 0) {
512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                createBitmap();
513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ByteBuffer buffer = (ByteBuffer) backing.lock(ACCESS_BYTES);
514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBitmap.copyPixelsFromBuffer(buffer);
515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                buffer.rewind();
516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_TEXTURE) != 0) {
517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                createBitmap();
518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                RenderTarget renderTarget = (RenderTarget) backing.lock(ACCESS_RENDERTARGET);
519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBitmap.copyPixelsFromBuffer(
520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        renderTarget.getPixelData(mDimensions[0], mDimensions[1]));
521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_ALLOCATION) != 0 && AllocationBacking.isSupported()) {
522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                createBitmap();
523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                syncToAllocationBacking(backing);
524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot sync bytebuffer backing!");
526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.unlock();
528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = false;
529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @TargetApi(11)
532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private void syncToAllocationBacking(Backing backing) {
533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Allocation allocation = (Allocation) backing.lock(ACCESS_ALLOCATION);
534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            allocation.copyTo(mBitmap);
535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Object lock(int accessType) {
539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mBitmap;
540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getType() {
544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return BACKING_BITMAP;
545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean shouldCache() {
549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requiresGpu() {
554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void destroy() {
559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // As we share the bitmap with other backings (such as object backings), we must not
560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // recycle it here.
561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBitmap = null;
562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return 4 * mDimensions[0] * mDimensions[1];
567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
568227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
569227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
570227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setData(Object data) {
571227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // We can assume that data will always be a Bitmap instance.
572227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBitmap = (Bitmap) data;
573227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
574227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
575227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private void createBitmap() {
576227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBitmap = Bitmap.createBitmap(mDimensions[0], mDimensions[1], Bitmap.Config.ARGB_8888);
577227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
578227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
579227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
580227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class TextureBacking extends Backing {
581227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
582227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private RenderTarget mRenderTarget = null;
583227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private TextureSource mTexture = null;
584227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
585227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
586227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void allocate(FrameType frameType) {
587227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            assertImageCompatible(frameType);
588227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mTexture = TextureSource.newTexture();
589227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
590227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
591227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
592227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int readAccess() {
593227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_TEXTURE;
594227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
595227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
596227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
597227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int writeAccess() {
598227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_RENDERTARGET;
599227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
600227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
601227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
602227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void syncTo(Backing backing) {
603227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int access = backing.readAccess();
604227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((access & ACCESS_BYTES) != 0) {
605227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ByteBuffer pixels = (ByteBuffer) backing.lock(ACCESS_BYTES);
606227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mTexture.allocateWithPixels(pixels, mDimensions[0], mDimensions[1]);
607227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BITMAP) != 0) {
608227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Bitmap bitmap = (Bitmap) backing.lock(ACCESS_BITMAP);
609227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mTexture.allocateWithBitmapPixels(bitmap);
610227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_TEXTURE) != 0) {
611227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                TextureSource texture = (TextureSource) backing.lock(ACCESS_TEXTURE);
612227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                int w = mDimensions[0];
613227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                int h = mDimensions[1];
614227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ImageShader.renderTextureToTarget(texture, getRenderTarget(), w, h);
615227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_ALLOCATION) != 0 && AllocationBacking.isSupported()) {
616227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                syncToAllocationBacking(backing);
617227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
618227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot sync bytebuffer backing!");
619227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
620227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.unlock();
621227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = false;
622227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
623227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
624227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @TargetApi(11)
625227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private void syncToAllocationBacking(Backing backing) {
626227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Allocation allocation = (Allocation) backing.lock(ACCESS_ALLOCATION);
627227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer pixels = ByteBuffer.allocateDirect(getSize());
628227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            allocation.copyTo(pixels.array());
629227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mTexture.allocateWithPixels(pixels, mDimensions[0], mDimensions[1]);
630227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
631227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
632227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
633227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Object lock(int accessType) {
634227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            switch (accessType) {
635227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_TEXTURE:
636227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return getTexture();
637227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
638227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case ACCESS_RENDERTARGET:
639227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return getRenderTarget();
640227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
641227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                default:
642227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new RuntimeException("Illegal access to texture!");
643227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
644227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
645227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
646227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
647227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getType() {
648227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return BACKING_TEXTURE;
649227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
650227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
651227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
652227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean shouldCache() {
653227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return true;
654227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
655227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
656227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
657227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requiresGpu() {
658227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return true;
659227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
660227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
661227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
662227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void destroy() {
663227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mRenderTarget != null) {
664227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mRenderTarget.release();
665227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
666227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mTexture.isAllocated()) {
667227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mTexture.release();
668227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
669227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
670227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
671227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
672227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
673227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return 4 * mDimensions[0] * mDimensions[1];
674227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
675227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
676227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private TextureSource getTexture() {
677227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (!mTexture.isAllocated()) {
678227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mTexture.allocate(mDimensions[0], mDimensions[1]);
679227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
680227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mTexture;
681227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
682227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
683227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private RenderTarget getRenderTarget() {
684227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mRenderTarget == null) {
685227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                int w = mDimensions[0];
686227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                int h = mDimensions[1];
687227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mRenderTarget = RenderTarget.currentTarget().forTexture(getTexture(), w, h);
688227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
689227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mRenderTarget;
690227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
691227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
692227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
693227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
694227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class ByteBufferBacking extends Backing {
695227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
696227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        ByteBuffer mBuffer = null;
697227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
698227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
699227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void allocate(FrameType frameType) {
700227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int size = frameType.getElementSize();
701227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int dim : mDimensions) {
702227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                size *= dim;
703227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
704227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBuffer = ByteBuffer.allocateDirect(size);
705227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
706227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
707227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
708227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int readAccess() {
709227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_BYTES;
710227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
711227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
712227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
713227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int writeAccess() {
714227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_BYTES;
715227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
716227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
717227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
718227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requiresGpu() {
719227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
720227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
721227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
722227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
723227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void syncTo(Backing backing) {
724227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int access = backing.readAccess();
725227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((access & ACCESS_TEXTURE) != 0) {
726227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                RenderTarget target = (RenderTarget) backing.lock(ACCESS_RENDERTARGET);
727227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                GLToolbox.readTarget(target, mBuffer, mDimensions[0], mDimensions[1]);
728227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BITMAP) != 0) {
729227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Bitmap bitmap = (Bitmap) backing.lock(ACCESS_BITMAP);
730227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                bitmap.copyPixelsToBuffer(mBuffer);
731227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBuffer.rewind();
732227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BYTES) != 0) {
733227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ByteBuffer otherBuffer = (ByteBuffer) backing.lock(ACCESS_BYTES);
734227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBuffer.put(otherBuffer);
735227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                otherBuffer.rewind();
736227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_ALLOCATION) != 0 && AllocationBacking.isSupported()) {
737227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                syncToAllocationBacking(backing);
738227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
739227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot sync bytebuffer backing!");
740227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
741227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.unlock();
742227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBuffer.rewind();
743227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = false;
744227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
745227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
746227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @TargetApi(11)
747227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private void syncToAllocationBacking(Backing backing) {
748227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Allocation allocation = (Allocation) backing.lock(ACCESS_ALLOCATION);
749227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (getElementId() == FrameType.ELEMENT_RGBA8888) {
750227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                byte[] bytes = mBuffer.array();
751227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                allocation.copyTo(bytes);
752227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if (getElementId() == FrameType.ELEMENT_FLOAT32) {
753227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                float[] floats = new float[getSize() / 4];
754227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                allocation.copyTo(floats);
755227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mBuffer.asFloatBuffer().put(floats);
756227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
757227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
758227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Trying to sync to an allocation with an unsupported element id: "
759227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        + getElementId());
760227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
761227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
762227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
763227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
764227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Object lock(int accessType) {
765227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mBuffer.rewind();
766227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
767227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
768227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
769227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void unlock() {
770227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBuffer.rewind();
771227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
772227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
773227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
774227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getType() {
775227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return BACKING_BYTEBUFFER;
776227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
777227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
778227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
779227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean shouldCache() {
780227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return true;
781227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
782227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
783227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
784227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void destroy() {
785227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBuffer = null;
786227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
787227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
788227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
789227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
790227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mBuffer.remaining();
791227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
792227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
793227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
794227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
795227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    @TargetApi(11)
796227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class AllocationBacking extends Backing {
797227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
798227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private final RenderScript mRenderScript;
799227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Allocation mAllocation = null;
800227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
801227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public AllocationBacking(RenderScript renderScript) {
802227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mRenderScript = renderScript;
803227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
804227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
805227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
806227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void allocate(FrameType frameType) {
807227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            assertCompatible(frameType);
808227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
809227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Element element = null;
810227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            switch (frameType.getElementId()) {
811227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case FrameType.ELEMENT_RGBA8888:
812227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    element = Element.RGBA_8888(mRenderScript);
813227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
814227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                case FrameType.ELEMENT_FLOAT32:
815227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    element = Element.F32(mRenderScript);
816227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    break;
817227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
818227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Type.Builder imageTypeBuilder = new Type.Builder(mRenderScript, element);
819227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            imageTypeBuilder.setX(mDimensions.length >= 1 ? mDimensions[0] : 1);
820227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            imageTypeBuilder.setY(mDimensions.length == 2 ? mDimensions[1] : 1);
821227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Type imageType = imageTypeBuilder.create();
822227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
823227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mAllocation = Allocation.createTyped(mRenderScript, imageType);
824227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
825227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
826227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
827227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int readAccess() {
828227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_ALLOCATION;
829227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
830227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
831227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
832227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int writeAccess() {
833227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return ACCESS_ALLOCATION;
834227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
835227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
836227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
837227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean requiresGpu() {
838227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
839227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
840227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
841227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
842227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void syncTo(Backing backing) {
843227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int access = backing.readAccess();
844227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((access & ACCESS_TEXTURE) != 0) {
845227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                RenderTarget target = (RenderTarget) backing.lock(ACCESS_RENDERTARGET);
846227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ByteBuffer pixels = ByteBuffer.allocateDirect(getSize());
847227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                GLToolbox.readTarget(target, pixels, mDimensions[0], mDimensions[1]);
848227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mAllocation.copyFrom(pixels.array());
849227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BITMAP) != 0) {
850227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Bitmap bitmap = (Bitmap) backing.lock(ACCESS_BITMAP);
851227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mAllocation.copyFrom(bitmap);
852227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else if ((access & ACCESS_BYTES) != 0) {
853227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                ByteBuffer buffer = (ByteBuffer) backing.lock(ACCESS_BYTES);
854227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (buffer.order() != ByteOrder.nativeOrder()) {
855227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    throw new RuntimeException(
856227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                            "Trying to sync to the ByteBufferBacking with non-native byte order!");
857227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
858227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                byte[] bytes;
859227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if (buffer.hasArray()) {
860227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    bytes = buffer.array();
861227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                } else {
862227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    bytes = new byte[getSize()];
863227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    buffer.get(bytes);
864227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    buffer.rewind();
865227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
866227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mAllocation.copyFromUnchecked(bytes);
867227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            } else {
868227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException("Cannot sync allocation backing!");
869227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
870227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.unlock();
871227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mIsDirty = false;
872227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
873227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
874227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
875227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Object lock(int accessType) {
876227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mAllocation;
877227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
878227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
879227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
880227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void unlock() {
881227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
882227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
883227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
884227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getType() {
885227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return BACKING_ALLOCATION;
886227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
887227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
888227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
889227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean shouldCache() {
890227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return true;
891227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
892227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
893227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
894227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void destroy() {
895227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mAllocation != null) {
896227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mAllocation.destroy();
897227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mAllocation = null;
898227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
899227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
900227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
901227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
902227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
903227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            int elementCount = 1;
904227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (int dim : mDimensions) {
905227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                elementCount *= dim;
906227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
907227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return getElementSize() * elementCount;
908227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
909227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
910227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public static boolean isSupported() {
911227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return Build.VERSION.SDK_INT >= 11;
912227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
913227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
914227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private void assertCompatible(FrameType type) {
915227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // TODO: consider adding support for other data types.
916227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (type.getElementId() != FrameType.ELEMENT_RGBA8888
917227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    && type.getElementId() != FrameType.ELEMENT_FLOAT32) {
918227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
919227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Cannot allocate allocation with a non-RGBA or non-float data type!");
920227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
921227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mDimensions == null || mDimensions.length > 2) {
922227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new RuntimeException(
923227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                        "Cannot create an allocation with more than 2 dimensions!");
924227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
925227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
926227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
927227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
928227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
929227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
930