SurfaceRenderFilter.java revision 692c3bf7a1c7e2d5b1066cf7a1b057e993742c87
130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/* 230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project 330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License"); 530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License. 630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at 730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * http://www.apache.org/licenses/LICENSE-2.0 930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software 1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS, 1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and 1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License. 1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 1630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipackage android.filterpacks.ui; 1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Filter; 21692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Rennimport android.filterfw.core.FilterContext; 2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FilterParameter; 2330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FilterSurfaceView; 2430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FilterSurfaceRenderer; 2530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Frame; 2630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FrameFormat; 2730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.GLEnvironment; 2830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.GLFrame; 2930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.KeyValueMap; 3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.MutableFrameFormat; 3130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.NativeProgram; 3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.NativeFrame; 3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Program; 3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.ShaderProgram; 3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.Surface; 3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.SurfaceHolder; 3830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.SurfaceView; 3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.graphics.Rect; 4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.util.Log; 4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronipublic class SurfaceRenderFilter extends Filter implements FilterSurfaceRenderer { 4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_STRETCH = 0; 4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_FIT = 1; 4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_FILL_CROP = 2; 4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni /** Required. Sets the destination filter surface view for this 5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * node. 5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @FilterParameter(name = "surfaceView", isOptional = false) 5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private FilterSurfaceView mSurfaceView; 5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni /** Optional. Control how the incoming frames are rendered onto the 5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * output. Default is FIT. 5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_STRETCH: Just fill the output surfaceView. 5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_FIT: Keep aspect ratio and fit without cropping. May 6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * have black bars. 6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_FILL_CROP: Keep aspect ratio and fit without black 6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * bars. May crop. 6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @FilterParameter(name = "renderMode", isOptional = true) 6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private String mRenderModeString; 6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private ShaderProgram mProgram; 6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private GLFrame mScreen; 6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mRenderMode = RENDERMODE_FIT; 7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private float mAspectRatio; 7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mScreenWidth; 7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mScreenHeight; 7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private static final boolean LOGV = false; 7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private static final String TAG = "SurfaceRenderFilter"; 7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public SurfaceRenderFilter(String name) { 7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni super(name); 8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni protected void finalize() throws Throwable { 8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mSurfaceView != null) { 8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mSurfaceView.unbind(); 8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public void initFilter() { 9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // SurfaceView 9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mSurfaceView == null) { 9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni throw new RuntimeException("NULL SurfaceView passed to SurfaceRenderFilter"); 9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // RenderMode 9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mRenderModeString != null) { 9730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mRenderModeString == "stretch") { 9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_STRETCH; 9930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (mRenderModeString == "fit") { 10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_FIT; 10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (mRenderModeString == "fill_crop") { 10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_FILL_CROP; 10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni throw new RuntimeException("Unknown render mode '" + mRenderModeString + "'!"); 10530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mAspectRatio = 1.f; 10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public String[] getInputNames() { 11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return new String[] { "frame" }; 11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public String[] getOutputNames() { 11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return null; 11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 12130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 122692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn public boolean acceptsInputFormat(int index, FrameFormat format) { 12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (format.isBinaryDataType() && 12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni format.getBytesPerSample() == 4 && 12530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni format.getNumberOfDimensions() == 2 && 12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni (format.getTarget() == FrameFormat.TARGET_NATIVE || 12730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni format.getTarget() == FrameFormat.TARGET_GPU)) { 12830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 13330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 13430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 135692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn public FrameFormat getOutputFormat(int index) { 13630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return null; 13730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 140692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn public void prepare(FilterContext environment) { 14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create identity shader to render, and make sure to render upside-down, as textures 14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // are stored internally bottom-to-top. 14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram = ShaderProgram.createIdentity(); 14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setSourceRect(0, 1, 1, -1); 14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setClearsOutput(true); 14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setClearColor(0.0f, 0.0f, 0.0f); 14730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni updateTargetRect(); 14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create a frame representing the screen 15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni MutableFrameFormat screenFormat = new MutableFrameFormat(FrameFormat.TYPE_BYTE, 15230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni FrameFormat.TARGET_GPU); 15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni screenFormat.setBytesPerSample(4); 15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni screenFormat.setDimensions(mSurfaceView.getWidth(), mSurfaceView.getHeight()); 15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreen = (GLFrame)environment.getFrameManager().newBoundFrame(screenFormat, 15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GLFrame.EXISTING_FBO_BINDING, 15730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0); 15830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 15930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind surface view to us. This will emit a surfaceChanged call that will update our 16030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // screen width and height. 16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mSurfaceView != null) { 16230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mSurfaceView.unbind(); 16330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mSurfaceView.bindToRenderer(this, environment.getGLEnvironment()); 16430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 16530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 16630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 168692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn public int process(FilterContext env) { 16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mSurfaceView != null) { 17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (LOGV) Log.v(TAG, "Starting frame processing"); 17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we are processing in the correct GL environment 17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GLEnvironment glEnv = mSurfaceView.getGLEnv(); 17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glEnv != env.getGLEnvironment()) { 17530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni throw new RuntimeException("Surface created under different GLEnvironment!"); 17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get input frame 17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni Frame input = pullInput(0); 18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni boolean createdFrame = false; 18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni float currentAspectRatio = (float)input.getFormat().getWidth() / input.getFormat().getHeight(); 18330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (currentAspectRatio != mAspectRatio) { 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (LOGV) Log.v(TAG, "New aspect ratio: " + currentAspectRatio +", previously: " + mAspectRatio); 18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mAspectRatio = currentAspectRatio; 18630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni updateTargetRect(); 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // See if we need to copy to GPU 19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni Frame gpuFrame = null; 19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (input.getFormat().getTarget() == FrameFormat.TARGET_NATIVE) { 19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni MutableFrameFormat gpuFormat = input.getFormat().mutableCopy(); 19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni gpuFormat.setTarget(FrameFormat.TARGET_GPU); 19430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni gpuFrame = env.getFrameManager().newFrame(gpuFormat); 19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni gpuFrame.setData(input.getData()); 19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni createdFrame = true; 19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni gpuFrame = input; 19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Activate our surface 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glEnv.activateSurfaceWithId(mSurfaceView.getSurfaceId()); 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Process 20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.process(gpuFrame, mScreen); 20630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // And swap buffers 20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glEnv.swapBuffers(); 20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (createdFrame) { 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni gpuFrame.release(); 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Wait for next input and free output 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return Filter.STATUS_WAIT_FOR_ALL_INPUTS | 21730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni Filter.STATUS_WAIT_FOR_FREE_OUTPUTS; 21830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 221692c3bf7a1c7e2d5b1066cf7a1b057e993742c87Marius Renn public void tearDown(FilterContext env) { 22230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreen != null) { 22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreen.release(); 22430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public synchronized void surfaceChanged(int format, int width, int height) { 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // If the screen is null, we do not care about surface changes (yet). Once we have a 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // screen object, we need to keep track of these changes. 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreen != null) { 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreenWidth = width; 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreenHeight = height; 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreen.setViewport(0, 0, mScreenWidth, mScreenHeight); 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni updateTargetRect(); 23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public synchronized void surfaceDestroyed() { 24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // We do nothing here but declare this synchronized so that the surface is not destroyed 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // behind our backs. 24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private void updateTargetRect() { 24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreenWidth > 0 && mScreenHeight > 0 && mProgram != null) { 24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni float screenAspectRatio = (float)mScreenWidth / mScreenHeight; 24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni float relativeAspectRatio = screenAspectRatio / mAspectRatio; 24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni switch (mRenderMode) { 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_STRETCH: 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0, 0, 1, 1); 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_FIT: 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (relativeAspectRatio > 1.0f) { 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is wider than the camera, scale down X 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f, 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f / relativeAspectRatio, 1.0f); 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is taller than the camera, scale down Y 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio, 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f, relativeAspectRatio); 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_FILL_CROP: 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (relativeAspectRatio > 1) { 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is wider than the camera, crop in Y 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio, 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f, relativeAspectRatio); 26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is taller than the camera, crop in X 27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f, 27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f / relativeAspectRatio, 1.0f); 27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni }; 27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 279