• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 package android.filterfw.core;
19 
20 import android.filterfw.core.Frame;
21 import android.filterfw.core.FrameFormat;
22 import android.filterfw.core.FrameManager;
23 import android.filterfw.core.NativeFrame;
24 import android.filterfw.core.StopWatchMap;
25 import android.graphics.Bitmap;
26 import android.opengl.GLES20;
27 import android.graphics.Rect;
28 
29 import java.nio.ByteBuffer;
30 
31 class GLFrameTimer {
32 
33     private static StopWatchMap mTimer = null;
34 
get()35     public static StopWatchMap get() {
36         if (mTimer == null) {
37             mTimer = new StopWatchMap();
38         }
39         return mTimer;
40     }
41 
42 }
43 
44 /**
45  * @hide
46  */
47 public class GLFrame extends Frame {
48 
49     // GL-related binding types
50     public final static int EXISTING_TEXTURE_BINDING = 100;
51     public final static int EXISTING_FBO_BINDING     = 101;
52     public final static int NEW_TEXTURE_BINDING      = 102; // TODO: REMOVE THIS
53     public final static int NEW_FBO_BINDING          = 103; // TODO: REMOVE THIS
54     public final static int EXTERNAL_TEXTURE         = 104;
55 
56     private int glFrameId = -1;
57 
58     /**
59      * Flag whether we own the texture or not. If we do not, we must be careful when caching or
60      * storing the frame, as the user may delete, and regenerate it.
61      */
62     private boolean mOwnsTexture = true;
63 
64     /**
65      * Keep a reference to the GL environment, so that it does not get deallocated while there
66      * are still frames living in it.
67      */
68     private GLEnvironment mGLEnvironment;
69 
GLFrame(FrameFormat format, FrameManager frameManager)70     GLFrame(FrameFormat format, FrameManager frameManager) {
71         super(format, frameManager);
72     }
73 
GLFrame(FrameFormat format, FrameManager frameManager, int bindingType, long bindingId)74     GLFrame(FrameFormat format, FrameManager frameManager, int bindingType, long bindingId) {
75         super(format, frameManager, bindingType, bindingId);
76     }
77 
init(GLEnvironment glEnv)78     void init(GLEnvironment glEnv) {
79         FrameFormat format = getFormat();
80         mGLEnvironment = glEnv;
81 
82         // Check that we have a valid format
83         if (format.getBytesPerSample() != 4) {
84             throw new IllegalArgumentException("GL frames must have 4 bytes per sample!");
85         } else if (format.getDimensionCount() != 2) {
86             throw new IllegalArgumentException("GL frames must be 2-dimensional!");
87         } else if (getFormat().getSize() < 0) {
88             throw new IllegalArgumentException("Initializing GL frame with zero size!");
89         }
90 
91         // Create correct frame
92         int bindingType = getBindingType();
93         boolean reusable = true;
94         if (bindingType == Frame.NO_BINDING) {
95             initNew(false);
96         } else if (bindingType == EXTERNAL_TEXTURE) {
97             initNew(true);
98             reusable = false;
99         } else if (bindingType == EXISTING_TEXTURE_BINDING) {
100             initWithTexture((int)getBindingId());
101         } else if (bindingType == EXISTING_FBO_BINDING) {
102             initWithFbo((int)getBindingId());
103         } else if (bindingType == NEW_TEXTURE_BINDING) {
104             initWithTexture((int)getBindingId());
105         } else if (bindingType == NEW_FBO_BINDING) {
106             initWithFbo((int)getBindingId());
107         } else {
108             throw new RuntimeException("Attempting to create GL frame with unknown binding type "
109                 + bindingType + "!");
110         }
111         setReusable(reusable);
112     }
113 
initNew(boolean isExternal)114     private void initNew(boolean isExternal) {
115         if (isExternal) {
116             if (!nativeAllocateExternal(mGLEnvironment)) {
117                 throw new RuntimeException("Could not allocate external GL frame!");
118             }
119         } else {
120             if (!nativeAllocate(mGLEnvironment, getFormat().getWidth(), getFormat().getHeight())) {
121                 throw new RuntimeException("Could not allocate GL frame!");
122             }
123         }
124     }
125 
initWithTexture(int texId)126     private void initWithTexture(int texId) {
127         int width = getFormat().getWidth();
128         int height = getFormat().getHeight();
129         if (!nativeAllocateWithTexture(mGLEnvironment, texId, width, height)) {
130             throw new RuntimeException("Could not allocate texture backed GL frame!");
131         }
132         mOwnsTexture = false;
133         markReadOnly();
134     }
135 
initWithFbo(int fboId)136     private void initWithFbo(int fboId) {
137         int width = getFormat().getWidth();
138         int height = getFormat().getHeight();
139         if (!nativeAllocateWithFbo(mGLEnvironment, fboId, width, height)) {
140             throw new RuntimeException("Could not allocate FBO backed GL frame!");
141         }
142     }
143 
flushGPU(String message)144     void flushGPU(String message) {
145         StopWatchMap timer = GLFrameTimer.get();
146         if (timer.LOG_MFF_RUNNING_TIMES) {
147           timer.start("glFinish " + message);
148           GLES20.glFinish();
149           timer.stop("glFinish " + message);
150         }
151     }
152 
153     @Override
hasNativeAllocation()154     protected synchronized boolean hasNativeAllocation() {
155         return glFrameId != -1;
156     }
157 
158     @Override
releaseNativeAllocation()159     protected synchronized void releaseNativeAllocation() {
160         nativeDeallocate();
161         glFrameId = -1;
162     }
163 
getGLEnvironment()164     public GLEnvironment getGLEnvironment() {
165         return mGLEnvironment;
166     }
167 
168     @Override
getObjectValue()169     public Object getObjectValue() {
170         assertGLEnvValid();
171         return ByteBuffer.wrap(getNativeData());
172     }
173 
174     @Override
setInts(int[] ints)175     public void setInts(int[] ints) {
176         assertFrameMutable();
177         assertGLEnvValid();
178         if (!setNativeInts(ints)) {
179             throw new RuntimeException("Could not set int values for GL frame!");
180         }
181     }
182 
183     @Override
getInts()184     public int[] getInts() {
185         assertGLEnvValid();
186         flushGPU("getInts");
187         return getNativeInts();
188     }
189 
190     @Override
setFloats(float[] floats)191     public void setFloats(float[] floats) {
192         assertFrameMutable();
193         assertGLEnvValid();
194         if (!setNativeFloats(floats)) {
195             throw new RuntimeException("Could not set int values for GL frame!");
196         }
197     }
198 
199     @Override
getFloats()200     public float[] getFloats() {
201         assertGLEnvValid();
202         flushGPU("getFloats");
203         return getNativeFloats();
204     }
205 
206     @Override
setData(ByteBuffer buffer, int offset, int length)207     public void setData(ByteBuffer buffer, int offset, int length) {
208         assertFrameMutable();
209         assertGLEnvValid();
210         byte[] bytes = buffer.array();
211         if (getFormat().getSize() != bytes.length) {
212             throw new RuntimeException("Data size in setData does not match GL frame size!");
213         } else if (!setNativeData(bytes, offset, length)) {
214             throw new RuntimeException("Could not set GL frame data!");
215         }
216     }
217 
218     @Override
getData()219     public ByteBuffer getData() {
220         assertGLEnvValid();
221         flushGPU("getData");
222         return ByteBuffer.wrap(getNativeData());
223     }
224 
225     @Override
setBitmap(Bitmap bitmap)226     public void setBitmap(Bitmap bitmap) {
227         assertFrameMutable();
228         assertGLEnvValid();
229         if (getFormat().getWidth()  != bitmap.getWidth() ||
230             getFormat().getHeight() != bitmap.getHeight()) {
231             throw new RuntimeException("Bitmap dimensions do not match GL frame dimensions!");
232         } else {
233             Bitmap rgbaBitmap = convertBitmapToRGBA(bitmap);
234             if (!setNativeBitmap(rgbaBitmap, rgbaBitmap.getByteCount())) {
235                 throw new RuntimeException("Could not set GL frame bitmap data!");
236             }
237         }
238     }
239 
240     @Override
getBitmap()241     public Bitmap getBitmap() {
242         assertGLEnvValid();
243         flushGPU("getBitmap");
244         Bitmap result = Bitmap.createBitmap(getFormat().getWidth(),
245                                             getFormat().getHeight(),
246                                             Bitmap.Config.ARGB_8888);
247         if (!getNativeBitmap(result)) {
248             throw new RuntimeException("Could not get bitmap data from GL frame!");
249         }
250         return result;
251     }
252 
253     @Override
setDataFromFrame(Frame frame)254     public void setDataFromFrame(Frame frame) {
255         assertGLEnvValid();
256 
257         // Make sure frame fits
258         if (getFormat().getSize() < frame.getFormat().getSize()) {
259             throw new RuntimeException(
260                 "Attempting to assign frame of size " + frame.getFormat().getSize() + " to " +
261                 "smaller GL frame of size " + getFormat().getSize() + "!");
262         }
263 
264         // Invoke optimized implementations if possible
265         if (frame instanceof NativeFrame) {
266             nativeCopyFromNative((NativeFrame)frame);
267         } else if (frame instanceof GLFrame) {
268             nativeCopyFromGL((GLFrame)frame);
269         } else if (frame instanceof SimpleFrame) {
270             setObjectValue(frame.getObjectValue());
271         } else {
272             super.setDataFromFrame(frame);
273         }
274     }
275 
setViewport(int x, int y, int width, int height)276     public void setViewport(int x, int y, int width, int height) {
277         assertFrameMutable();
278         setNativeViewport(x, y, width, height);
279     }
280 
setViewport(Rect rect)281     public void setViewport(Rect rect) {
282         assertFrameMutable();
283         setNativeViewport(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
284     }
285 
generateMipMap()286     public void generateMipMap() {
287         assertFrameMutable();
288         assertGLEnvValid();
289         if (!generateNativeMipMap()) {
290             throw new RuntimeException("Could not generate mip-map for GL frame!");
291         }
292     }
293 
setTextureParameter(int param, int value)294     public void setTextureParameter(int param, int value) {
295         assertFrameMutable();
296         assertGLEnvValid();
297         if (!setNativeTextureParam(param, value)) {
298             throw new RuntimeException("Could not set texture value " + param + " = " + value + " " +
299                                        "for GLFrame!");
300         }
301     }
302 
getTextureId()303     public int getTextureId() {
304         return getNativeTextureId();
305     }
306 
getFboId()307     public int getFboId() {
308         return getNativeFboId();
309     }
310 
focus()311     public void focus() {
312         if (!nativeFocus()) {
313             throw new RuntimeException("Could not focus on GLFrame for drawing!");
314         }
315     }
316 
317     @Override
toString()318     public String toString() {
319         return "GLFrame id: " + glFrameId + " (" + getFormat() + ") with texture ID "
320             + getTextureId() + ", FBO ID " + getFboId();
321     }
322 
323     @Override
reset(FrameFormat newFormat)324     protected void reset(FrameFormat newFormat) {
325         if (!nativeResetParams()) {
326             throw new RuntimeException("Could not reset GLFrame texture parameters!");
327         }
328         super.reset(newFormat);
329     }
330 
331     @Override
onFrameStore()332     protected void onFrameStore() {
333         if (!mOwnsTexture) {
334             // Detach texture from FBO in case user manipulates it.
335             nativeDetachTexFromFbo();
336         }
337     }
338 
339     @Override
onFrameFetch()340     protected void onFrameFetch() {
341         if (!mOwnsTexture) {
342             // Reattach texture to FBO when using frame again. This may reallocate the texture
343             // in case it has become invalid.
344             nativeReattachTexToFbo();
345         }
346     }
347 
assertGLEnvValid()348     private void assertGLEnvValid() {
349         if (!mGLEnvironment.isContextActive()) {
350             if (GLEnvironment.isAnyContextActive()) {
351                 throw new RuntimeException("Attempting to access " + this + " with foreign GL " +
352                     "context active!");
353             } else {
354                 throw new RuntimeException("Attempting to access " + this + " with no GL context " +
355                     " active!");
356             }
357         }
358     }
359 
360     static {
361         System.loadLibrary("filterfw");
362     }
363 
nativeAllocate(GLEnvironment env, int width, int height)364     private native boolean nativeAllocate(GLEnvironment env, int width, int height);
365 
nativeAllocateWithTexture(GLEnvironment env, int textureId, int width, int height)366     private native boolean nativeAllocateWithTexture(GLEnvironment env,
367                                                int textureId,
368                                                int width,
369                                                int height);
370 
nativeAllocateWithFbo(GLEnvironment env, int fboId, int width, int height)371     private native boolean nativeAllocateWithFbo(GLEnvironment env,
372                                            int fboId,
373                                            int width,
374                                            int height);
375 
nativeAllocateExternal(GLEnvironment env)376     private native boolean nativeAllocateExternal(GLEnvironment env);
377 
nativeDeallocate()378     private native boolean nativeDeallocate();
379 
setNativeData(byte[] data, int offset, int length)380     private native boolean setNativeData(byte[] data, int offset, int length);
381 
getNativeData()382     private native byte[] getNativeData();
383 
setNativeInts(int[] ints)384     private native boolean setNativeInts(int[] ints);
385 
setNativeFloats(float[] floats)386     private native boolean setNativeFloats(float[] floats);
387 
getNativeInts()388     private native int[] getNativeInts();
389 
getNativeFloats()390     private native float[] getNativeFloats();
391 
setNativeBitmap(Bitmap bitmap, int size)392     private native boolean setNativeBitmap(Bitmap bitmap, int size);
393 
getNativeBitmap(Bitmap bitmap)394     private native boolean getNativeBitmap(Bitmap bitmap);
395 
setNativeViewport(int x, int y, int width, int height)396     private native boolean setNativeViewport(int x, int y, int width, int height);
397 
getNativeTextureId()398     private native int getNativeTextureId();
399 
getNativeFboId()400     private native int getNativeFboId();
401 
generateNativeMipMap()402     private native boolean generateNativeMipMap();
403 
setNativeTextureParam(int param, int value)404     private native boolean setNativeTextureParam(int param, int value);
405 
nativeResetParams()406     private native boolean nativeResetParams();
407 
nativeCopyFromNative(NativeFrame frame)408     private native boolean nativeCopyFromNative(NativeFrame frame);
409 
nativeCopyFromGL(GLFrame frame)410     private native boolean nativeCopyFromGL(GLFrame frame);
411 
nativeFocus()412     private native boolean nativeFocus();
413 
nativeReattachTexToFbo()414     private native boolean nativeReattachTexToFbo();
415 
nativeDetachTexFromFbo()416     private native boolean nativeDetachTexFromFbo();
417 }
418