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");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport androidx.media.filterfw.BackingStore.Backing;
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Arrays;
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Comparator;
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashMap;
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.HashSet;
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Map;
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.PriorityQueue;
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.util.Set;
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The FrameManager tracks, caches, allocates and deallocates frame data.
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * All Frame instances are managed by a FrameManager, and belong to exactly one of these. Frames
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * cannot be shared across FrameManager instances, however multiple MffContexts may use the same
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * FrameManager.
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Additionally, frame managers allow attaching Frames under a specified key. This allows decoupling
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * filter-graphs by instructing one node to attach a frame under a specific key, and another to
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * fetch the frame under the same key.
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class FrameManager {
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** The default max cache size is set to 12 MB */
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int DEFAULT_MAX_CACHE_SIZE = 12 * 1024 * 1024;
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Frame caching policy: No caching */
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int FRAME_CACHE_NONE = 0;
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Frame caching policy: Drop least recently used frame buffers */
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int FRAME_CACHE_LRU = 1;
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Frame caching policy: Drop least frequently used frame buffers */
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int FRAME_CACHE_LFU = 2;
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Slot Flag: No flags set */
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int SLOT_FLAGS_NONE = 0x00;
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /** Slot Flag: Sticky flag set: Frame will remain in slot after fetch. */
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public final static int SLOT_FLAG_STICKY = 0x01;
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private GraphRunner mRunner;
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Set<Backing> mBackings = new HashSet<Backing>();
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private BackingCache mCache;
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private Map<String, FrameSlot> mFrameSlots = new HashMap<String, FrameSlot>();
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static class FrameSlot {
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private FrameType mType;
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private int mFlags;
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private Frame mFrame = null;
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public FrameSlot(FrameType type, int flags) {
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mType = type;
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFlags = flags;
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public FrameType getType() {
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mType;
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean hasFrame() {
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mFrame != null;
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void releaseFrame() {
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mFrame != null) {
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mFrame.release();
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mFrame = null;
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        // TODO: Type check
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void assignFrame(Frame frame) {
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Frame oldFrame = mFrame;
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mFrame = frame.retain();
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (oldFrame != null) {
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                oldFrame.release();
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Frame getFrame() {
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            Frame result = mFrame.retain();
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if ((mFlags & SLOT_FLAG_STICKY) == 0) {
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                releaseFrame();
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return result;
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void markWritable() {
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (mFrame != null) {
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mFrame.setReadOnly(false);
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static abstract class BackingCache {
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected int mCacheMaxSize = DEFAULT_MAX_CACHE_SIZE;
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract Backing fetchBacking(int mode, int access, int[] dimensions, int elemSize);
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract boolean cacheBacking(Backing backing);
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract void clear();
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public abstract int getSizeLeft();
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void setSize(int size) {
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mCacheMaxSize = size;
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mCacheMaxSize;
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class BackingCacheNone extends BackingCache {
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Backing fetchBacking(int mode, int access, int[] dimensions, int elemSize) {
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return null;
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean cacheBacking(Backing backing) {
141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void clear() {
146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSize() {
150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return 0;
151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSizeLeft() {
155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return 0;
156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static abstract class PriorityBackingCache extends BackingCache {
160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private int mSize = 0;
161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private PriorityQueue<Backing> mQueue;
162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public PriorityBackingCache() {
164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mQueue = new PriorityQueue<Backing>(4, new Comparator<Backing>() {
165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                @Override
166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                public int compare(Backing left, Backing right) {
167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return left.cachePriority - right.cachePriority;
168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            });
170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public Backing fetchBacking(int mode, int access, int[] dimensions, int elemSize) {
174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            for (Backing backing : mQueue) {
175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                int backingAccess = (mode == Frame.MODE_WRITE)
176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    ? backing.writeAccess()
177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    : backing.readAccess();
178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                if ((backingAccess & access) == access
179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    && dimensionsCompatible(backing.getDimensions(), dimensions)
180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    && (elemSize == backing.getElementSize())) {
181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mQueue.remove(backing);
182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    mSize -= backing.getSize();
183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    onFetchBacking(backing);
184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    return backing;
185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                }
186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.w("FrameManager", "Could not find backing for dimensions " + Arrays.toString(dimensions));
188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return null;
189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public boolean cacheBacking(Backing backing) {
193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (reserve(backing.getSize())) {
194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                onCacheBacking(backing);
195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mQueue.add(backing);
196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                return true;
197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return false;
199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public void clear() {
203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mQueue.clear();
204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSize = 0;
205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        public int getSizeLeft() {
209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return mCacheMaxSize - mSize;
210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected abstract void onCacheBacking(Backing backing);
213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected abstract void onFetchBacking(Backing backing);
215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private boolean reserve(int size) {
217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.i("FM", "Reserving " + size + " bytes (max: " + mCacheMaxSize + " bytes).");
218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.i("FM", "Current size " + mSize);
219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            if (size > mCacheMaxSize) {
220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                return false;
221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mSize += size;
223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            while (mSize > mCacheMaxSize) {
224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                Backing dropped = mQueue.poll();
225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mSize -= dropped.getSize();
226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                //Log.i("FM", "Dropping  " + dropped + " with priority "
227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                //    + dropped.cachePriority + ". New size: " + mSize + "!");
228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                dropped.destroy();
229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            }
230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            return true;
231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class BackingCacheLru extends PriorityBackingCache {
237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        private int mTimestamp = 0;
238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected void onCacheBacking(Backing backing) {
241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.cachePriority = 0;
242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected void onFetchBacking(Backing backing) {
246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ++mTimestamp;
247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.cachePriority = mTimestamp;
248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static class BackingCacheLfu extends PriorityBackingCache {
252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected void onCacheBacking(Backing backing) {
254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.cachePriority = 0;
255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        @Override
258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        protected void onFetchBacking(Backing backing) {
259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ++backing.cachePriority;
260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static FrameManager current() {
264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        GraphRunner runner = GraphRunner.current();
265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return runner != null ? runner.getFrameManager() : null;
266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the context that the FrameManager is bound to.
270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the MffContext instance that the FrameManager is bound to.
272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public MffContext getContext() {
274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mRunner.getContext();
275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the GraphRunner that the FrameManager is bound to.
279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the GraphRunner instance that the FrameManager is bound to.
281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public GraphRunner getRunner() {
283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mRunner;
284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Sets the size of the cache.
288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Resizes the cache to the specified size in bytes.
290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param bytes the new size in bytes.
292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void setCacheSize(int bytes) {
294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCache.setSize(bytes);
295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Returns the size of the cache.
299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @return the size of the cache in bytes.
301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public int getCacheSize() {
303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mCache.getSize();
304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Imports a frame from another FrameManager.
308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * This will return a frame with the contents of the given frame for use in this FrameManager.
310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Note, that there is a substantial cost involved in moving a Frame from one FrameManager to
311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * another. This may be called from any thread. After the frame has been imported, it may be
312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * used in the runner that uses this FrameManager. As the new frame may share data with the
313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * provided frame, that frame must be read-only.
314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param frame The frame to import
316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Frame importFrame(Frame frame) {
318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!frame.isReadOnly()) {
319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Frame " + frame + " must be read-only to import "
320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "into another FrameManager!");
321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return frame.makeCpuCopy(this);
323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Adds a new frame slot to the frame manager.
327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Filters can reference frame slots to pass frames between graphs or runs. If the name
328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * specified here is already taken the frame slot is overwritten. You can only
329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * modify frame-slots while no graph of the frame manager is running.
330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param name The name of the slot.
332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param type The type of Frame that will be assigned to this slot.
333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param flags A mask of {@code SLOT} flags.
334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void addFrameSlot(String name, FrameType type, int flags) {
336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertNotRunning();
337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameSlot oldSlot = mFrameSlots.get(name);
338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (oldSlot != null) {
339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            removeFrameSlot(name);
340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameSlot slot = new FrameSlot(type, flags);
342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFrameSlots.put(name, slot);
343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Removes a frame slot from the frame manager.
347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Any frame within the slot is released. You can only modify frame-slots while no graph
348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * of the frame manager is running.
349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param name The name of the slot
351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @throws IllegalArgumentException if no such slot exists.
352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void removeFrameSlot(String name) {
354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertNotRunning();
355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameSlot slot = getSlot(name);
356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        slot.releaseFrame();
357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mFrameSlots.remove(slot);
358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * TODO: Document!
362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void storeFrame(Frame frame, String slotName) {
364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertInGraphRun();
365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        getSlot(slotName).assignFrame(frame);
366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * TODO: Document!
370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public Frame fetchFrame(String slotName) {
372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        assertInGraphRun();
373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return getSlot(slotName).getFrame();
374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Clears the Frame cache.
378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public void clearCache() {
380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCache.clear();
381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Create a new FrameManager instance.
385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Creates a new FrameManager instance in the specified context and employing a cache with the
387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * specified cache type (see the cache type constants defined by the FrameManager class).
388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param runner the GraphRunner to bind the FrameManager to.
390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param cacheType the type of cache to use.
391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    FrameManager(GraphRunner runner, int cacheType) {
393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mRunner = runner;
394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        switch (cacheType) {
395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            case FRAME_CACHE_NONE:
396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCache = new BackingCacheNone();
397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                break;
398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            case FRAME_CACHE_LRU:
399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCache = new BackingCacheLru();
400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                break;
401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            case FRAME_CACHE_LFU:
402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                mCache = new BackingCacheLfu();
403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                break;
404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            default:
405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                throw new IllegalArgumentException("Unknown cache-type " + cacheType + "!");
406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    Backing fetchBacking(int mode, int access, int[] dimensions, int elemSize) {
410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return mCache.fetchBacking(mode, access, dimensions, elemSize);
411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void onBackingCreated(Backing backing) {
414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (backing != null) {
415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBackings.add(backing);
416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            // Log.i("FrameManager", "RM: Now have " + mBackings.size() + " backings");
417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void onBackingAvailable(Backing backing) {
421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!backing.shouldCache() || !mCache.cacheBacking(backing)) {
422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.destroy();
423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            mBackings.remove(backing);
424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            //Log.i("FrameManager", "RM: Now have " + mBackings.size() + " backings (" + mCache.getSizeLeft() + ")");
425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Destroying all references makes any Frames that contain them invalid.
430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void destroyBackings() {
432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (Backing backing : mBackings) {
433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            backing.destroy();
434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mBackings.clear();
436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        mCache.clear();
437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    FrameSlot getSlot(String name) {
440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        FrameSlot slot = mFrameSlots.get(name);
441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (slot == null) {
442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Unknown frame slot '" + name + "'!");
443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return slot;
445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void onBeginRun() {
448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        for (FrameSlot slot : mFrameSlots.values()) {
449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            slot.markWritable();
450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    // Internals ///////////////////////////////////////////////////////////////////////////////////
454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static boolean dimensionsCompatible(int[] dimA, int[] dimB) {
455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        return dimA == null || dimB == null || Arrays.equals(dimA, dimB);
456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void assertNotRunning() {
459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (mRunner.isRunning()) {
460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Attempting to modify FrameManager while graph is "
461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + "running!");
462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private void assertInGraphRun() {
466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (!mRunner.isRunning() || GraphRunner.current() != mRunner) {
467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalStateException("Attempting to access FrameManager Frame data "
468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                + "outside of graph run-loop!");
469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
474