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 18package android.filterfw.core; 19 20import android.content.Context; 21import android.util.AttributeSet; 22import android.view.SurfaceHolder; 23import android.view.SurfaceView; 24 25/** 26 * @hide 27 */ 28public class FilterSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 29 30 private static int STATE_ALLOCATED = 0; 31 private static int STATE_CREATED = 1; 32 private static int STATE_INITIALIZED = 2; 33 34 private int mState = STATE_ALLOCATED; 35 private SurfaceHolder.Callback mListener; 36 private GLEnvironment mGLEnv; 37 private int mFormat; 38 private int mWidth; 39 private int mHeight; 40 private int mSurfaceId = -1; 41 42 public FilterSurfaceView(Context context) { 43 super(context); 44 getHolder().addCallback(this); 45 } 46 47 public FilterSurfaceView(Context context, AttributeSet attrs) { 48 super(context, attrs); 49 getHolder().addCallback(this); 50 } 51 52 public synchronized void bindToListener(SurfaceHolder.Callback listener, GLEnvironment glEnv) { 53 // Make sure we are not bound already 54 if (listener == null) { 55 throw new NullPointerException("Attempting to bind null filter to SurfaceView!"); 56 } else if (mListener != null && mListener != listener) { 57 throw new RuntimeException( 58 "Attempting to bind filter " + listener + " to SurfaceView with another open " 59 + "filter " + mListener + " attached already!"); 60 } 61 62 // Set listener 63 mListener = listener; 64 65 // Set GLEnv 66 if (mGLEnv != null && mGLEnv != glEnv) { 67 mGLEnv.unregisterSurfaceId(mSurfaceId); 68 } 69 mGLEnv = glEnv; 70 71 // Check if surface has been created already 72 if (mState >= STATE_CREATED) { 73 // Register with env (double registration will be ignored by GLEnv, so we can simply 74 // try to do it here). 75 registerSurface(); 76 77 // Forward surface created to listener 78 mListener.surfaceCreated(getHolder()); 79 80 // Forward surface changed to listener 81 if (mState == STATE_INITIALIZED) { 82 mListener.surfaceChanged(getHolder(), mFormat, mWidth, mHeight); 83 } 84 } 85 } 86 87 public synchronized void unbind() { 88 mListener = null; 89 } 90 91 public synchronized int getSurfaceId() { 92 return mSurfaceId; 93 } 94 95 public synchronized GLEnvironment getGLEnv() { 96 return mGLEnv; 97 } 98 99 @Override 100 public synchronized void surfaceCreated(SurfaceHolder holder) { 101 mState = STATE_CREATED; 102 103 // Register with GLEnvironment if we have it already 104 if (mGLEnv != null) { 105 registerSurface(); 106 } 107 108 // Forward callback to listener 109 if (mListener != null) { 110 mListener.surfaceCreated(holder); 111 } 112 } 113 114 @Override 115 public synchronized void surfaceChanged(SurfaceHolder holder, 116 int format, 117 int width, 118 int height) { 119 // Remember these values 120 mFormat = format; 121 mWidth = width; 122 mHeight = height; 123 mState = STATE_INITIALIZED; 124 125 // Forward to renderer 126 if (mListener != null) { 127 mListener.surfaceChanged(holder, format, width, height); 128 } 129 } 130 131 @Override 132 public synchronized void surfaceDestroyed(SurfaceHolder holder) { 133 mState = STATE_ALLOCATED; 134 135 // Forward to renderer 136 if (mListener != null) { 137 mListener.surfaceDestroyed(holder); 138 } 139 140 // Get rid of internal objects associated with this surface 141 unregisterSurface(); 142 } 143 144 private void registerSurface() { 145 mSurfaceId = mGLEnv.registerSurface(getHolder().getSurface()); 146 if (mSurfaceId < 0) { 147 throw new RuntimeException("Could not register Surface: " + getHolder().getSurface() + 148 " in FilterSurfaceView!"); 149 } 150 } 151 private void unregisterSurface() { 152 if (mGLEnv != null && mSurfaceId > 0) { 153 mGLEnv.unregisterSurfaceId(mSurfaceId); 154 } 155 } 156 157} 158