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.FilterSurfaceView; 2330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.Frame; 2430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.filterfw.core.FrameFormat; 2521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GenerateFieldPort; 2621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.core.GenerateFinalPort; 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; 3521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Rennimport android.filterfw.format.ImageFormat; 3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.Surface; 3830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.SurfaceHolder; 3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.view.SurfaceView; 4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.graphics.Rect; 4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniimport android.util.Log; 4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 45a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala/** 46a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala * @hide 47a3bfbe5389c6146abe318a7add3fa688d69bc01bEino-Ville Talvala */ 488bdaff4e029bfac893ea652702e4e685130f28e9Marius Rennpublic class SurfaceRenderFilter extends Filter implements SurfaceHolder.Callback { 4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_STRETCH = 0; 5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_FIT = 1; 5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private final int RENDERMODE_FILL_CROP = 2; 5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni /** Required. Sets the destination filter surface view for this 5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * node. 5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 5721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFinalPort(name = "surfaceView") 5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private FilterSurfaceView mSurfaceView; 5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni /** Optional. Control how the incoming frames are rendered onto the 6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * output. Default is FIT. 6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_STRETCH: Just fill the output surfaceView. 6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_FIT: Keep aspect ratio and fit without cropping. May 6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * have black bars. 6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * RENDERMODE_FILL_CROP: Keep aspect ratio and fit without black 6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * bars. May crop. 6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 6821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @GenerateFieldPort(name = "renderMode", hasDefault = true) 6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private String mRenderModeString; 7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 718bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn private boolean mIsBound = false; 728bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn 7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private ShaderProgram mProgram; 7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private GLFrame mScreen; 7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mRenderMode = RENDERMODE_FIT; 7621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn private float mAspectRatio = 1.f; 7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mScreenWidth; 7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private int mScreenHeight; 8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8157774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala private boolean mLogVerbose; 8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private static final String TAG = "SurfaceRenderFilter"; 8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni public SurfaceRenderFilter(String name) { 8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni super(name); 8657774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala 8757774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); 8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 9121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void setupPorts() { 9221d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn // Make sure we have a SurfaceView 9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mSurfaceView == null) { 9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni throw new RuntimeException("NULL SurfaceView passed to SurfaceRenderFilter"); 9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn // Add input port 9821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn addMaskedInputPort("frame", ImageFormat.create(ImageFormat.COLORSPACE_RGBA)); 9921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } 10021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn 10121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void updateRenderMode() { 10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mRenderModeString != null) { 103427833087f412e3bcbe4e31945ea1461f3c4824aRuei-sung Lin if (mRenderModeString.equals("stretch")) { 10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_STRETCH; 105427833087f412e3bcbe4e31945ea1461f3c4824aRuei-sung Lin } else if (mRenderModeString.equals("fit")) { 10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_FIT; 107427833087f412e3bcbe4e31945ea1461f3c4824aRuei-sung Lin } else if (mRenderModeString.equals("fill_crop")) { 10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mRenderMode = RENDERMODE_FILL_CROP; 10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni throw new RuntimeException("Unknown render mode '" + mRenderModeString + "'!"); 11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn updateTargetRect(); 11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 117a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala public void prepare(FilterContext context) { 11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create identity shader to render, and make sure to render upside-down, as textures 11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // are stored internally bottom-to-top. 120511360e61650864ea22a171159efe073c80d0cdbMarius Renn mProgram = ShaderProgram.createIdentity(context); 12130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setSourceRect(0, 1, 1, -1); 12230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setClearsOutput(true); 12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setClearColor(0.0f, 0.0f, 0.0f); 12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 12521d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn updateRenderMode(); 12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 12730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create a frame representing the screen 128e4c7423f1bbcb79ba9317f09d0da7038ea6bb0b5Marius Renn MutableFrameFormat screenFormat = ImageFormat.create(mSurfaceView.getWidth(), 129e4c7423f1bbcb79ba9317f09d0da7038ea6bb0b5Marius Renn mSurfaceView.getHeight(), 130e4c7423f1bbcb79ba9317f09d0da7038ea6bb0b5Marius Renn ImageFormat.COLORSPACE_RGBA, 131e4c7423f1bbcb79ba9317f09d0da7038ea6bb0b5Marius Renn FrameFormat.TARGET_GPU); 132a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala mScreen = (GLFrame)context.getFrameManager().newBoundFrame(screenFormat, 13321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn GLFrame.EXISTING_FBO_BINDING, 13421d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn 0); 135a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala } 136a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala 137a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala @Override 13821d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void open(FilterContext context) { 1398bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn // Bind surface view to us. This will emit a surfaceCreated and surfaceChanged call that 1408bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn // will update our screen width and height. 141a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala mSurfaceView.unbind(); 1428bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn mSurfaceView.bindToListener(this, context.getGLEnvironment()); 14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 14621d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void process(FilterContext context) { 1478bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn // Make sure we are bound to a surface before rendering 1488bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn if (!mIsBound) { 1498bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn Log.w("SurfaceRenderFilter", 1508bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn this + ": Ignoring frame as there is no surface to render to!"); 1518bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn return; 1528bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn } 1538bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn 15457774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "Starting frame processing"); 15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 156a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala GLEnvironment glEnv = mSurfaceView.getGLEnv(); 157a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala if (glEnv != context.getGLEnvironment()) { 158a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala throw new RuntimeException("Surface created under different GLEnvironment!"); 159a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala } 16030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 162a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala // Get input frame 16321d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn Frame input = pullInput("frame"); 164a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala boolean createdFrame = false; 16530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 166a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala float currentAspectRatio = (float)input.getFormat().getWidth() / input.getFormat().getHeight(); 167a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala if (currentAspectRatio != mAspectRatio) { 16857774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala if (mLogVerbose) Log.v(TAG, "New aspect ratio: " + currentAspectRatio +", previously: " + mAspectRatio); 169a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala mAspectRatio = currentAspectRatio; 170a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala updateTargetRect(); 171a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala } 172a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala 173a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala // See if we need to copy to GPU 174a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala Frame gpuFrame = null; 17557774b9e8ea96fa5088e68bac7a21465fa429b15Eino-Ville Talvala if (mLogVerbose) Log.v("SurfaceRenderFilter", "Got input format: " + input.getFormat()); 176262184714f14ddbff3b8d418091c687416d2a14aMarius Renn int target = input.getFormat().getTarget(); 177262184714f14ddbff3b8d418091c687416d2a14aMarius Renn if (target != FrameFormat.TARGET_GPU) { 178262184714f14ddbff3b8d418091c687416d2a14aMarius Renn gpuFrame = context.getFrameManager().duplicateFrameToTarget(input, 179262184714f14ddbff3b8d418091c687416d2a14aMarius Renn FrameFormat.TARGET_GPU); 180a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala createdFrame = true; 181a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala } else { 182a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala gpuFrame = input; 183a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala } 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 185a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala // Activate our surface 186a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala glEnv.activateSurfaceWithId(mSurfaceView.getSurfaceId()); 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 188a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala // Process 189a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala mProgram.process(gpuFrame, mScreen); 19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 191a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala // And swap buffers 192a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala glEnv.swapBuffers(); 19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 194a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala if (createdFrame) { 195a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala gpuFrame.release(); 19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 19721d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn } 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 19921d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn @Override 20021d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn public void fieldPortValueUpdated(String name, FilterContext context) { 20121d0ac7403b836e32e2bdbdc8dc98f42b2dfa4e5Marius Renn updateTargetRect(); 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 2058bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn public void close(FilterContext context) { 2068bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn mSurfaceView.unbind(); 2078bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn } 2088bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn 2098bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn @Override 210a9ccdef84f787fde226b6b49b6a29db9dc099a4bEino-Ville Talvala public void tearDown(FilterContext context) { 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreen != null) { 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreen.release(); 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni @Override 2178bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn public synchronized void surfaceCreated(SurfaceHolder holder) { 2188bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn mIsBound = true; 2198bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn } 2208bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn 2218bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn @Override 2228bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn public synchronized void surfaceChanged(SurfaceHolder holder, 2238bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn int format, 2248bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn int width, 2258bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn int height) { 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // If the screen is null, we do not care about surface changes (yet). Once we have a 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // screen object, we need to keep track of these changes. 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreen != null) { 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreenWidth = width; 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreenHeight = height; 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mScreen.setViewport(0, 0, mScreenWidth, mScreenHeight); 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni updateTargetRect(); 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23633d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua @Override 2378bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn public synchronized void surfaceDestroyed(SurfaceHolder holder) { 2388bdaff4e029bfac893ea652702e4e685130f28e9Marius Renn mIsBound = false; 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni private void updateTargetRect() { 24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (mScreenWidth > 0 && mScreenHeight > 0 && mProgram != null) { 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni float screenAspectRatio = (float)mScreenWidth / mScreenHeight; 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni float relativeAspectRatio = screenAspectRatio / mAspectRatio; 24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni switch (mRenderMode) { 24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_STRETCH: 24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0, 0, 1, 1); 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_FIT: 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (relativeAspectRatio > 1.0f) { 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is wider than the camera, scale down X 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f, 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f / relativeAspectRatio, 1.0f); 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is taller than the camera, scale down Y 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio, 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f, relativeAspectRatio); 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni case RENDERMODE_FILL_CROP: 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (relativeAspectRatio > 1) { 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is wider than the camera, crop in Y 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.0f, 0.5f - 0.5f * relativeAspectRatio, 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f, relativeAspectRatio); 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else { 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Screen is taller than the camera, crop in X 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni mProgram.setTargetRect(0.5f - 0.5f / relativeAspectRatio, 0.0f, 26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1.0f / relativeAspectRatio, 1.0f); 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni break; 27233d107bf315c9cc01a02a7a4a2c10a01f62e8c85Wei Hua } 27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 276