1274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen/* 2274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Copyright (C) 2011 The Android Open Source Project 3274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * 4274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 5274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * you may not use this file except in compliance with the License. 6274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * You may obtain a copy of the License at 7274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * 8274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 9274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * 10274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * Unless required by applicable law or agreed to in writing, software 11274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 12274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * See the License for the specific language governing permissions and 14274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen * limitations under the License. 15274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen */ 16274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen 17274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <GLES2/gl2.h> 18274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <GLES2/gl2ext.h> 19eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include <jni.h> 20274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <math.h> 21274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <stdio.h> 22274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include <stdlib.h> 23274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "db_utilities_camera.h" 24eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include "mosaic/ImageUtils.h" 25eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include "mosaic_renderer/FrameBuffer.h" 26eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal#include "mosaic_renderer/WarpRenderer.h" 2741a2e9735136f372de95652d0828600282c8e967mbansal#include "mosaic_renderer/SurfaceTextureRenderer.h" 281e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include "mosaic_renderer/YVURenderer.h" 29eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 30274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "mosaic/Log.h" 31274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#define LOG_TAG "MosaicRenderer" 32eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 33274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen#include "mosaic_renderer_jni.h" 34eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 35eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// Texture handle 3641a2e9735136f372de95652d0828600282c8e967mbansalGLuint gSurfaceTextureID[1]; 37eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 3841a2e9735136f372de95652d0828600282c8e967mbansalbool gWarpImage = true; 39eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Low-Res input image frame in YUVA format for preview rendering and processing 411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// and high-res YUVA input image for processing. 421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalunsigned char* gPreviewImage[NR]; 4341a2e9735136f372de95652d0828600282c8e967mbansal// Low-Res & high-res preview image width 441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalint gPreviewImageWidth[NR]; 4541a2e9735136f372de95652d0828600282c8e967mbansal// Low-Res & high-res preview image height 461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalint gPreviewImageHeight[NR]; 47eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Semaphore to protect simultaneous read/writes from gPreviewImage 491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalsem_t gPreviewImage_semaphore; 50eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 51eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// Off-screen preview FBO width (large enough to store the entire 52eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// preview mosaic). 53eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalint gPreviewFBOWidth; 54eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// Off-screen preview FBO height (large enough to store the entire 55eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// preview mosaic). 56eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalint gPreviewFBOHeight; 57eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 58a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// gK is the transformation to map the canonical {-1,1} vertex coordinate system 59a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// to the {0,gPreviewImageWidth[LR]} input image frame coordinate system before 60a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// applying the given affine transformation trs. gKm is the corresponding 61a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// transformation for going to the {0,gPreviewFBOWidth}. 62a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gK[9]; 63a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gKinv[9]; 64a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gKm[9]; 65a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gKminv[9]; 66a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 6741a2e9735136f372de95652d0828600282c8e967mbansal// Shader to copy input SurfaceTexture into and RGBA FBO. The two shaders 6841a2e9735136f372de95652d0828600282c8e967mbansal// render to the textures with dimensions corresponding to the low-res and 6941a2e9735136f372de95652d0828600282c8e967mbansal// high-res image frames. 7041a2e9735136f372de95652d0828600282c8e967mbansalSurfaceTextureRenderer gSurfTexRenderer[NR]; 7141a2e9735136f372de95652d0828600282c8e967mbansal// Off-screen FBOs to store the low-res and high-res RGBA copied out from 7241a2e9735136f372de95652d0828600282c8e967mbansal// the SurfaceTexture by the gSurfTexRenderers. 7341a2e9735136f372de95652d0828600282c8e967mbansalFrameBuffer gBufferInput[NR]; 741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Shader to convert RGBA textures into YVU textures for processing 761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalYVURenderer gYVURenderer[NR]; 771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Off-screen FBOs to store the low-res and high-res YVU textures for processing 781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalFrameBuffer gBufferInputYVU[NR]; 791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 8047f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen// Shader to translate the flip-flop FBO - gBuffer[1-current] -> gBuffer[current] 811e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalWarpRenderer gWarper1; 8247f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen// Shader to add warped current frame to the flip-flop FBO - gBuffer[current] 831e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalWarpRenderer gWarper2; 841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Off-screen FBOs (flip-flop) to store the result of gWarper1 & gWarper2 851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalFrameBuffer gBuffer[2]; 861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 87eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// Shader to warp and render the preview FBO to the screen 88eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalWarpRenderer gPreview; 891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Index of the gBuffer FBO gWarper1 is going to write into 911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalint gCurrentFBOIndex = 0; 921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 93a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// 3x3 Matrices holding the transformation of this frame (gThisH1t) and of 94a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// the last frame (gLastH1t) w.r.t the first frame. 95a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gThisH1t[9]; 96a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gLastH1t[9]; 97a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 98a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// Variables to represent the fixed position of the top-left corner of the 99a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// current frame in the previewFBO 100a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gCenterOffsetX = 0.0f; 101a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gCenterOffsetY = 0.0f; 102a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 103a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// X-Offset of the viewfinder (current frame) w.r.t 104a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// (gCenterOffsetX, gCenterOffsetY). This offset varies with time and is 105a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// used to pan the viewfinder across the UI layout. 106a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gPanOffset = 0.0f; 1071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 1081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// Variables tracking the translation value for the current frame and the 1091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// last frame (both w.r.t the first frame). The difference between these 1101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// values is used to control the panning speed of the viewfinder display 1111e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// on the UI screen. 1121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansaldouble gThisTx = 0.0f; 1131e762b1f935c9d4a06af6dd56121590ca81d48b1mbansaldouble gLastTx = 0.0f; 114eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 115a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// These are the scale factors used by the gPreview shader to ensure that 116a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// the image frame is correctly scaled to the full UI layout height while 117a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// maintaining its aspect ratio 118a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gUILayoutScalingX = 1.0f; 119a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble gUILayoutScalingY = 1.0f; 120a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 121d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen// Whether the view that we will render preview FBO onto is in landscape or portrait 122d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen// orientation. 123d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chenbool gIsLandscapeOrientation = true; 124d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 125a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// State of the viewfinder. Set to false when the viewfinder hits the UI edge. 126a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansalbool gPanViewfinder = true; 127a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 128eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// Affine transformation in GL 4x4 format (column-major) to warp the 129a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// last frame mosaic into the current frame coordinate system. 130eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalGLfloat g_dAffinetransGL[16]; 131a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble g_dAffinetrans[16]; 132eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 133a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// Affine transformation in GL 4x4 format (column-major) to translate the 134a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// preview FBO across the screen (viewfinder panning). 135a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansalGLfloat g_dAffinetransPanGL[16]; 136a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble g_dAffinetransPan[16]; 137eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 138a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// XY translation in GL 4x4 format (column-major) to center the current 139a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// preview mosaic in the preview FBO 140a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansalGLfloat g_dTranslationToFBOCenterGL[16]; 141a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansaldouble g_dTranslationToFBOCenter[16]; 1421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 143eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// GL 4x4 Identity transformation 144d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta ChenGLfloat g_dAffinetransIdentGL[] = { 145eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 1., 0., 0., 0., 146eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 0., 1., 0., 0., 147eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 0., 0., 1., 0., 148eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 0., 0., 0., 1.}; 149eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 150d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen// GL 4x4 Rotation transformation (column-majored): 90 degree 151d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta ChenGLfloat g_dAffinetransRotation90GL[] = { 152d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 0., 1., 0., 0., 153d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen -1., 0., 0., 0., 154d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 0., 0., 1., 0., 155d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 0., 0., 0., 1.}; 156d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 157d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen// 3x3 Rotation transformation (row-majored): 90 degree 158d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chendouble gRotation90[] = { 159d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 0., -1., 0., 160d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 1., 0., 0., 161d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 0., 0., 1.,}; 162d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 163d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 1641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalfloat g_dIdent3x3[] = { 1651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 1.0, 0.0, 0.0, 1661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 0.0, 1.0, 0.0, 1671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 0.0, 0.0, 1.0}; 1681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 16941a2e9735136f372de95652d0828600282c8e967mbansalconst int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65; 170eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 171eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalstatic void printGLString(const char *name, GLenum s) { 172eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal const char *v = (const char *) glGetString(s); 173274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGI("GL %s = %s", name, v); 174eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 175eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 176eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal// @return false if there was an error 177eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalbool checkGlError(const char* op) { 178eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal GLint error = glGetError(); 179eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal if (error != 0) { 180274ca49c63557a8c3ee12c8da5f75e28b4875a5dWei-Ta Chen LOGE("after %s() glError (0x%x)", op, error); 181eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal return false; 182eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal } 183eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal return true; 184eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 185eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 18641a2e9735136f372de95652d0828600282c8e967mbansalvoid bindSurfaceTexture(GLuint texId) 187eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 18841a2e9735136f372de95652d0828600282c8e967mbansal glBindTexture(GL_TEXTURE_EXTERNAL_OES_ENUM, texId); 18941a2e9735136f372de95652d0828600282c8e967mbansal 19041a2e9735136f372de95652d0828600282c8e967mbansal // Can't do mipmapping with camera source 19141a2e9735136f372de95652d0828600282c8e967mbansal glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MIN_FILTER, 19241a2e9735136f372de95652d0828600282c8e967mbansal GL_LINEAR); 19341a2e9735136f372de95652d0828600282c8e967mbansal glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MAG_FILTER, 19441a2e9735136f372de95652d0828600282c8e967mbansal GL_LINEAR); 19541a2e9735136f372de95652d0828600282c8e967mbansal // Clamp to edge is the only option 19641a2e9735136f372de95652d0828600282c8e967mbansal glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_S, 19741a2e9735136f372de95652d0828600282c8e967mbansal GL_CLAMP_TO_EDGE); 19841a2e9735136f372de95652d0828600282c8e967mbansal glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_T, 19941a2e9735136f372de95652d0828600282c8e967mbansal GL_CLAMP_TO_EDGE); 200eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 201eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 2021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalvoid ClearPreviewImage(int mID) 203eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 2041e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal unsigned char* ptr = gPreviewImage[mID]; 20541a2e9735136f372de95652d0828600282c8e967mbansal for(int j = 0, i = 0; 2061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal j < gPreviewImageWidth[mID] * gPreviewImageHeight[mID] * 4; 20741a2e9735136f372de95652d0828600282c8e967mbansal j += 4) 20841a2e9735136f372de95652d0828600282c8e967mbansal { 20941a2e9735136f372de95652d0828600282c8e967mbansal ptr[i++] = 0; 21041a2e9735136f372de95652d0828600282c8e967mbansal ptr[i++] = 0; 21141a2e9735136f372de95652d0828600282c8e967mbansal ptr[i++] = 0; 21241a2e9735136f372de95652d0828600282c8e967mbansal ptr[i++] = 255; 21341a2e9735136f372de95652d0828600282c8e967mbansal } 21441a2e9735136f372de95652d0828600282c8e967mbansal 215eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 216eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 217eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalvoid ConvertAffine3x3toGL4x4(double *matGL44, double *mat33) 218eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 219eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[0] = mat33[0]; 220eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[1] = mat33[3]; 221eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[2] = 0.0; 222eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[3] = mat33[6]; 223eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 224eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[4] = mat33[1]; 225eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[5] = mat33[4]; 226eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[6] = 0.0; 227eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[7] = mat33[7]; 228eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 229eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[8] = 0; 230eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[9] = 0; 231eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[10] = 1.0; 232eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[11] = 0.0; 233eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 234eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[12] = mat33[2]; 235eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[13] = mat33[5]; 236eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[14] = 0.0; 237eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal matGL44[15] = mat33[8]; 238eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 239eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 240d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chenbool continuePanningFBO(double panOffset) { 241d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen double normalizedScreenLimitLeft = -1.0 + VIEWPORT_BORDER_FACTOR_HORZ * 2.0; 242d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen double normalizedScreenLimitRight = 1.0 - VIEWPORT_BORDER_FACTOR_HORZ * 2.0; 243d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen double normalizedXPositionOnScreenLeft; 244d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen double normalizedXPositionOnScreenRight; 245d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 246d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Compute the position of the current frame in the screen coordinate system 247d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen if (gIsLandscapeOrientation) { 248d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen normalizedXPositionOnScreenLeft = (2.0 * 249d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) * 250d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingX; 251d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen normalizedXPositionOnScreenRight = (2.0 * 252d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) / 253d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gPreviewFBOWidth - 1.0) * gUILayoutScalingX; 254d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } else { 255d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen normalizedXPositionOnScreenLeft = (2.0 * 256d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) * 257d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingY; 258d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen normalizedXPositionOnScreenRight = (2.0 * 259d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) / 260d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gPreviewFBOWidth - 1.0) * gUILayoutScalingY; 261d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } 262d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 263d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Stop the viewfinder panning if we hit the maximum border allowed for 264d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // this UI layout 265d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen if (normalizedXPositionOnScreenRight > normalizedScreenLimitRight || 266d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen normalizedXPositionOnScreenLeft < normalizedScreenLimitLeft) { 267d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen return false; 268d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } else { 269d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen return true; 270d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } 271d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen} 272d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 2731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// This function computes fills the 4x4 matrices g_dAffinetrans, 274a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// and g_dAffinetransPan using the specified 3x3 affine 2751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal// transformation between the first captured frame and the current frame. 276a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// The computed g_dAffinetrans is such that it warps the preview mosaic in 277a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// the last frame's coordinate system into the coordinate system of the 278a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// current frame. Thus, applying this transformation will create the current 279a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// frame mosaic but with the current frame missing. This frame will then be 280a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// pasted in by gWarper2 after translating it by g_dTranslationToFBOCenter. 281a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// The computed g_dAffinetransPan is such that it offsets the computed preview 282a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal// mosaic horizontally to make the viewfinder pan within the UI layout. 283eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalvoid UpdateWarpTransformation(float *trs) 284eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 285a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal double H[9], Hp[9], Htemp1[9], Htemp2[9], T[9]; 286eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 287a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal for(int i = 0; i < 9; i++) 288eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal { 289a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gThisH1t[i] = trs[i]; 290eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal } 291eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 29247f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // Alignment is done based on low-res data. 29347f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // To render the preview mosaic, the translation of the high-res mosaic is estimated to 29447f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // H2L_FACTOR x low-res-based tranlation. 29547f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gThisH1t[2] *= H2L_FACTOR; 29647f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gThisH1t[5] *= H2L_FACTOR; 29747f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen 298a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(T); 299a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal T[2] = -gCenterOffsetX; 300a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal T[5] = -gCenterOffsetY; 301a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 302a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // H = ( inv(gThisH1t) * gLastH1t ) * T 303a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(Htemp1); 304a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(Htemp2); 305a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(H); 306a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_InvertAffineTransform(Htemp1, gThisH1t); 307a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Htemp2, Htemp1, gLastH1t); 308a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(H, Htemp2, T); 309a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 310a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal for(int i = 0; i < 9; i++) 311a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal { 312a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gLastH1t[i] = gThisH1t[i]; 313a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal } 3141e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 315eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal // Move the origin such that the frame is centered in the previewFBO 316a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // i.e. H = inv(T) * H 317a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal H[2] += gCenterOffsetX; 318a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal H[5] += gCenterOffsetY; 319eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 32047f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // Hp = inv(Km) * H * Km 32147f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // Km moves the coordinate system from openGL to image pixels so 3221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal // that the alignment transform H can be applied to them. 32347f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // inv(Km) moves the coordinate system back to openGL normalized 3241e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal // coordinates so that the shader can correctly render it. 325a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(Htemp1); 326a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Htemp1, H, gKm); 327a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Hp, gKminv, Htemp1); 328eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 329eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal ConvertAffine3x3toGL4x4(g_dAffinetrans, Hp); 330eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 331a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal //////////////////////////////////////////////// 332a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal ////// Compute g_dAffinetransPan now... ////// 333a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal //////////////////////////////////////////////// 334eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 335a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gThisTx = trs[2]; 336eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 337a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal if(gPanViewfinder) 338a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal { 339a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPanOffset += (gThisTx - gLastTx) * VIEWFINDER_PAN_FACTOR_HORZ; 340a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal } 3411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 3421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gLastTx = gThisTx; 343d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gPanViewfinder = continuePanningFBO(gPanOffset); 344eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 345a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(H); 346a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal H[2] = gPanOffset; 3471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 34847f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // Hp = inv(Km) * H * Km 349a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(Htemp1); 350a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Htemp1, H, gKm); 351a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Hp, gKminv, Htemp1); 3521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 353d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen if (gIsLandscapeOrientation) { 354d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen ConvertAffine3x3toGL4x4(g_dAffinetransPan, Hp); 355d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } else { 356d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // rotate Hp by 90 degress. 357d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen db_Multiply3x3_3x3(Htemp1, gRotation90, Hp); 358d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen ConvertAffine3x3toGL4x4(g_dAffinetransPan, Htemp1); 359d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } 360eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 361eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 36241a2e9735136f372de95652d0828600282c8e967mbansalvoid AllocateTextureMemory(int widthHR, int heightHR, int widthLR, int heightLR) 363eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 3641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageWidth[HR] = widthHR; 3651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[HR] = heightHR; 3661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 3671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageWidth[LR] = widthLR; 3681e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[LR] = heightLR; 36941a2e9735136f372de95652d0828600282c8e967mbansal 3701e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_init(&gPreviewImage_semaphore, 0, 1); 371eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 3721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_wait(&gPreviewImage_semaphore); 3731e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImage[LR] = ImageUtils::allocateImage(gPreviewImageWidth[LR], 3741e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[LR], 4); 3751e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ClearPreviewImage(LR); 3761e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImage[HR] = ImageUtils::allocateImage(gPreviewImageWidth[HR], 3771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[HR], 4); 3781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ClearPreviewImage(HR); 3791e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_post(&gPreviewImage_semaphore); 380eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 38147f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[HR]; 38247f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[HR]; 383eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 384a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // The origin is such that the current frame will sit with its center 385a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // at the center of the previewFBO 38647f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gCenterOffsetX = (gPreviewFBOWidth / 2 - gPreviewImageWidth[HR] / 2); 38747f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gCenterOffsetY = (gPreviewFBOHeight / 2 - gPreviewImageHeight[HR] / 2); 388a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 389a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPanOffset = 0.0f; 390a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 391a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gThisH1t); 392a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gLastH1t); 393a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 394a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPanViewfinder = true; 395a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 39647f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen int w = gPreviewImageWidth[HR]; 39747f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen int h = gPreviewImageHeight[HR]; 398a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 399a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal int wm = gPreviewFBOWidth; 400a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal int hm = gPreviewFBOHeight; 401a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 402a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // K is the transformation to map the canonical [-1,1] vertex coordinate 403a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // system to the [0,w] image coordinate system before applying the given 404a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // affine transformation trs. 405a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[0] = wm / 2.0 - 0.5; 406a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[1] = 0.0; 407a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[2] = wm / 2.0 - 0.5; 408a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[3] = 0.0; 409a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[4] = hm / 2.0 - 0.5; 410a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[5] = hm / 2.0 - 0.5; 411a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[6] = 0.0; 412a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[7] = 0.0; 413a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gKm[8] = 1.0; 414a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 415a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[0] = w / 2.0 - 0.5; 416a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[1] = 0.0; 417a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[2] = w / 2.0 - 0.5; 418a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[3] = 0.0; 419a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[4] = h / 2.0 - 0.5; 420a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[5] = h / 2.0 - 0.5; 421a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[6] = 0.0; 422a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[7] = 0.0; 423a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gK[8] = 1.0; 424a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 425a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gKinv); 426a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_InvertCalibrationMatrix(gKinv, gK); 427a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 428a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gKminv); 429a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_InvertCalibrationMatrix(gKminv, gKm); 430a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 431a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal ////////////////////////////////////////// 432a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal ////// Compute g_Translation now... ////// 433a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal ////////////////////////////////////////// 434a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal double T[9], Tp[9], Ttemp[9]; 435a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 436a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(T); 437a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal T[2] = gCenterOffsetX; 438a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal T[5] = gCenterOffsetY; 439a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 440a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // Tp = inv(K) * T * K 441a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(Ttemp); 442a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Ttemp, T, gK); 443a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Multiply3x3_3x3(Tp, gKinv, Ttemp); 444a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 445a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal ConvertAffine3x3toGL4x4(g_dTranslationToFBOCenter, Tp); 446eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 4471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal UpdateWarpTransformation(g_dIdent3x3); 448eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 449eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 450eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalvoid FreeTextureMemory() 451eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 4521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_wait(&gPreviewImage_semaphore); 4531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ImageUtils::freeImage(gPreviewImage[LR]); 4541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ImageUtils::freeImage(gPreviewImage[HR]); 4551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_post(&gPreviewImage_semaphore); 456eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 4571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_destroy(&gPreviewImage_semaphore); 458eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 459eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 460eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalextern "C" 461eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 46241a2e9735136f372de95652d0828600282c8e967mbansal JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( 463eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj); 464eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( 465d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen JNIEnv * env, jobject obj, jint width, jint height, 466d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen jboolean isLandscapeOrientation); 46741a2e9735136f372de95652d0828600282c8e967mbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( 46841a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj, jfloatArray stMatrix); 46941a2e9735136f372de95652d0828600282c8e967mbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( 47041a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj); 471eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( 472eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj); 473eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( 474eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj); 47541a2e9735136f372de95652d0828600282c8e967mbansal JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( 47641a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj, jboolean flag); 477eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal}; 478eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 47941a2e9735136f372de95652d0828600282c8e967mbansalJNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( 480eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj) 481eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 48241a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].InitializeGLProgram(); 48341a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].InitializeGLProgram(); 4841e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].InitializeGLProgram(); 4851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].InitializeGLProgram(); 4861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.InitializeGLProgram(); 4871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper2.InitializeGLProgram(); 488eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal gPreview.InitializeGLProgram(); 4891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBuffer[0].InitializeGLContext(); 4901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBuffer[1].InitializeGLContext(); 49141a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[LR].InitializeGLContext(); 49241a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[HR].InitializeGLContext(); 4931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInputYVU[LR].InitializeGLContext(); 4941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInputYVU[HR].InitializeGLContext(); 495eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 496eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal glBindFramebuffer(GL_FRAMEBUFFER, 0); 49741a2e9735136f372de95652d0828600282c8e967mbansal 49841a2e9735136f372de95652d0828600282c8e967mbansal glGenTextures(1, gSurfaceTextureID); 49941a2e9735136f372de95652d0828600282c8e967mbansal // bind the surface texture 50041a2e9735136f372de95652d0828600282c8e967mbansal bindSurfaceTexture(gSurfaceTextureID[0]); 50141a2e9735136f372de95652d0828600282c8e967mbansal 50241a2e9735136f372de95652d0828600282c8e967mbansal return (jint) gSurfaceTextureID[0]; 503eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 504eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 50541a2e9735136f372de95652d0828600282c8e967mbansal 506d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chenvoid calculateUILayoutScaling(int width, int height, bool isLandscape) { 507d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen if (isLandscape) { 508d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // __________ ______ 509d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // |__________| => |______| 510d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // (Preview FBO) (View) 511d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // 512d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Scale the preview FBO's height to the height of view and 513d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // maintain the aspect ratio of the current frame on the screen. 514d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingY = PREVIEW_FBO_HEIGHT_SCALE; 515d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 516d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Note that OpenGL scales a texture to view's width and height automatically. 517d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // The "width / height" inverts the scaling, so as to maintain the aspect ratio 518d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // of the current frame. 519d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingX = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR]) 520d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) * PREVIEW_FBO_HEIGHT_SCALE) 521d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen / ((float) width / height); 522d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } else { 523d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // __ 524d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // __________ | | 525d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // |__________| => | | 526d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // (Preview FBO) | | 527d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // |__| 528d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // (View) 529d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Scale the preview FBO's height to the width of view and 530d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // maintain the aspect ratio of the current frame on the screen. 531d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingX = PREVIEW_FBO_HEIGHT_SCALE; 532d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 533d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Note that OpenGL scales a texture to view's width and height automatically. 534d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // The "height / width" inverts the scaling, so as to maintain the aspect ratio 535d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // of the current frame. 536d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gUILayoutScalingY = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR]) 537d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) * PREVIEW_FBO_HEIGHT_SCALE) 538d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen / ((float) height / width); 539d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 540d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } 541d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen} 542d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 543eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( 544d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen JNIEnv * env, jobject obj, jint width, jint height, jboolean isLandscapeOrientation) 545eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 546d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gIsLandscapeOrientation = isLandscapeOrientation; 547d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen calculateUILayoutScaling(width, height, gIsLandscapeOrientation); 54885dedb803016feea39a78efc4bfc07b4f436cc6cWei-Ta Chen 5491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBuffer[0].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); 5501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBuffer[1].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); 5511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 5521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInput[LR].Init(gPreviewImageWidth[LR], 5531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[LR], GL_RGBA); 5541e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 5551e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInput[HR].Init(gPreviewImageWidth[HR], 5561e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[HR], GL_RGBA); 55741a2e9735136f372de95652d0828600282c8e967mbansal 5581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInputYVU[LR].Init(gPreviewImageWidth[LR], 5591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[LR], GL_RGBA); 56041a2e9735136f372de95652d0828600282c8e967mbansal 5611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gBufferInputYVU[HR].Init(gPreviewImageWidth[HR], 5621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImageHeight[HR], GL_RGBA); 563eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 5641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_wait(&gPreviewImage_semaphore); 5651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ClearPreviewImage(LR); 5661e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal ClearPreviewImage(HR); 5671e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_post(&gPreviewImage_semaphore); 568eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 56941a2e9735136f372de95652d0828600282c8e967mbansal // bind the surface texture 57041a2e9735136f372de95652d0828600282c8e967mbansal bindSurfaceTexture(gSurfaceTextureID[0]); 57141a2e9735136f372de95652d0828600282c8e967mbansal 57241a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetupGraphics(&gBufferInput[LR]); 57341a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); 57441a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetViewportMatrix(1, 1, 1, 1); 57541a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetScalingMatrix(1.0f, -1.0f); 57641a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetInputTextureName(gSurfaceTextureID[0]); 57741a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); 578eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 57941a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetupGraphics(&gBufferInput[HR]); 58041a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); 58141a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetViewportMatrix(1, 1, 1, 1); 58241a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetScalingMatrix(1.0f, -1.0f); 58341a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetInputTextureName(gSurfaceTextureID[0]); 58441a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); 58541a2e9735136f372de95652d0828600282c8e967mbansal 5861e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].SetupGraphics(&gBufferInputYVU[LR]); 5871e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); 5881e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].SetInputTextureName(gBufferInput[LR].GetTextureName()); 5891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].SetInputTextureType(GL_TEXTURE_2D); 5901e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 5911e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].SetupGraphics(&gBufferInputYVU[HR]); 5921e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); 5931e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].SetInputTextureName(gBufferInput[HR].GetTextureName()); 5941e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].SetInputTextureType(GL_TEXTURE_2D); 5951e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 596a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // gBuffer[1-gCurrentFBOIndex] --> gWarper1 --> gBuffer[gCurrentFBOIndex] 5971e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 5981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 599a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.SetViewportMatrix(1, 1, 1, 1); 6001e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.SetScalingMatrix(1.0f, 1.0f); 601a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.SetInputTextureName(gBuffer[1 - gCurrentFBOIndex].GetTextureName()); 6021e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.SetInputTextureType(GL_TEXTURE_2D); 6031e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 60447f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen // gBufferInput[HR] --> gWarper2 --> gBuffer[gCurrentFBOIndex] 605a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 6061e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper2.Clear(0.0, 0.0, 0.0, 1.0); 60747f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gWarper2.SetViewportMatrix(gPreviewImageWidth[HR], 60847f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gPreviewImageHeight[HR], gBuffer[gCurrentFBOIndex].GetWidth(), 609a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gBuffer[gCurrentFBOIndex].GetHeight()); 6101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper2.SetScalingMatrix(1.0f, 1.0f); 61147f3bff0df080af493ddae1857b82370b592e2f7Wei-Ta Chen gWarper2.SetInputTextureName(gBufferInput[HR].GetTextureName()); 6121e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper2.SetInputTextureType(GL_TEXTURE_2D); 613eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 614eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal gPreview.SetupGraphics(width, height); 615eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal gPreview.Clear(0.0, 0.0, 0.0, 1.0); 616eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal gPreview.SetViewportMatrix(1, 1, 1, 1); 617d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 6181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal // Scale the previewFBO so that the viewfinder window fills the layout height 6191e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal // while maintaining the image aspect ratio 620a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPreview.SetScalingMatrix(gUILayoutScalingX, -1.0f * gUILayoutScalingY); 621a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 62241a2e9735136f372de95652d0828600282c8e967mbansal gPreview.SetInputTextureType(GL_TEXTURE_2D); 62341a2e9735136f372de95652d0828600282c8e967mbansal} 62441a2e9735136f372de95652d0828600282c8e967mbansal 62541a2e9735136f372de95652d0828600282c8e967mbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( 62641a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj, jfloatArray stMatrix) 62741a2e9735136f372de95652d0828600282c8e967mbansal{ 62841a2e9735136f372de95652d0828600282c8e967mbansal jfloat *stmat = env->GetFloatArrayElements(stMatrix, 0); 62941a2e9735136f372de95652d0828600282c8e967mbansal 63041a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[LR].SetSTMatrix((float*) stmat); 63141a2e9735136f372de95652d0828600282c8e967mbansal gSurfTexRenderer[HR].SetSTMatrix((float*) stmat); 63241a2e9735136f372de95652d0828600282c8e967mbansal 63341a2e9735136f372de95652d0828600282c8e967mbansal env->ReleaseFloatArrayElements(stMatrix, stmat, 0); 63441a2e9735136f372de95652d0828600282c8e967mbansal 635d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gSurfTexRenderer[LR].DrawTexture(g_dAffinetransIdentGL); 636d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gSurfTexRenderer[HR].DrawTexture(g_dAffinetransIdentGL); 63741a2e9735136f372de95652d0828600282c8e967mbansal} 63841a2e9735136f372de95652d0828600282c8e967mbansal 6391e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#ifndef now_ms 6401e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#include <time.h> 6411e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalstatic double 6421e762b1f935c9d4a06af6dd56121590ca81d48b1mbansalnow_ms(void) 6431e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal{ 6441e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal //struct timespec res; 6451e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal struct timeval res; 6461e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal //clock_gettime(CLOCK_REALTIME, &res); 6471e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gettimeofday(&res, NULL); 6481e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; 6491e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal} 6501e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal#endif 6511e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 6521e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 6531e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 65441a2e9735136f372de95652d0828600282c8e967mbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( 65541a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj) 65641a2e9735136f372de95652d0828600282c8e967mbansal{ 6571e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal double t0, t1, time_c; 6581e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 6591e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[LR].DrawTexture(); 6601e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gYVURenderer[HR].DrawTexture(); 6611e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 6621e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_wait(&gPreviewImage_semaphore); 66341a2e9735136f372de95652d0828600282c8e967mbansal // Bind to the input LR FBO and read the Low-Res data from there... 6641e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[LR].GetFrameBufferName()); 6651e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal t0 = now_ms(); 66641a2e9735136f372de95652d0828600282c8e967mbansal glReadPixels(0, 66741a2e9735136f372de95652d0828600282c8e967mbansal 0, 66841a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[LR].GetWidth(), 66941a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[LR].GetHeight(), 67041a2e9735136f372de95652d0828600282c8e967mbansal GL_RGBA, 67141a2e9735136f372de95652d0828600282c8e967mbansal GL_UNSIGNED_BYTE, 6721e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImage[LR]); 67341a2e9735136f372de95652d0828600282c8e967mbansal 67441a2e9735136f372de95652d0828600282c8e967mbansal checkGlError("glReadPixels LR"); 67541a2e9735136f372de95652d0828600282c8e967mbansal 67641a2e9735136f372de95652d0828600282c8e967mbansal // Bind to the input HR FBO and read the high-res data from there... 6771e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[HR].GetFrameBufferName()); 6781e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal t0 = now_ms(); 67941a2e9735136f372de95652d0828600282c8e967mbansal glReadPixels(0, 68041a2e9735136f372de95652d0828600282c8e967mbansal 0, 68141a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[HR].GetWidth(), 68241a2e9735136f372de95652d0828600282c8e967mbansal gBufferInput[HR].GetHeight(), 68341a2e9735136f372de95652d0828600282c8e967mbansal GL_RGBA, 68441a2e9735136f372de95652d0828600282c8e967mbansal GL_UNSIGNED_BYTE, 6851e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreviewImage[HR]); 68641a2e9735136f372de95652d0828600282c8e967mbansal 68741a2e9735136f372de95652d0828600282c8e967mbansal checkGlError("glReadPixels HR"); 68841a2e9735136f372de95652d0828600282c8e967mbansal 6891e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal sem_post(&gPreviewImage_semaphore); 690eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 691eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 692eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( 693eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj) 694eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 695a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal if(!gWarpImage) // ViewFinder 6961e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal { 697a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 6981e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 6991e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 700a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); 701d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen 702d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen if (gIsLandscapeOrientation) { 703d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gPreview.DrawTexture(g_dAffinetransIdentGL); 704d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } else { 705d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen gPreview.DrawTexture(g_dAffinetransRotation90GL); 706d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen } 7071e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal } 7081e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal else 7091e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal { 7101e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 711a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // Clear the destination so that we can paint on it afresh 712a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 713a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.SetInputTextureName( 714a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gBuffer[1 - gCurrentFBOIndex].GetTextureName()); 715a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); 716a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); 717eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 7181e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.DrawTexture(g_dAffinetransGL); 719a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); 720a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPreview.DrawTexture(g_dAffinetransPanGL); 7211e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal 7221e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gCurrentFBOIndex = 1 - gCurrentFBOIndex; 7231e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal } 724eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 725eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 72641a2e9735136f372de95652d0828600282c8e967mbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( 72741a2e9735136f372de95652d0828600282c8e967mbansal JNIEnv * env, jobject obj, jboolean flag) 728eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 72941a2e9735136f372de95652d0828600282c8e967mbansal // TODO: Review this logic 73041a2e9735136f372de95652d0828600282c8e967mbansal if(gWarpImage != (bool) flag) //switching from viewfinder to capture or vice-versa 73141a2e9735136f372de95652d0828600282c8e967mbansal { 732a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // Clear gBuffer[0] 733a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.SetupGraphics(&gBuffer[0]); 734a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 735a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal // Clear gBuffer[1] 736a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gWarper1.SetupGraphics(&gBuffer[1]); 7371e762b1f935c9d4a06af6dd56121590ca81d48b1mbansal gWarper1.Clear(0.0, 0.0, 0.0, 1.0); 73841a2e9735136f372de95652d0828600282c8e967mbansal // Clear the screen to black. 739a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPreview.Clear(0.0, 0.0, 0.0, 1.0); 740a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 741a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gLastTx = 0.0f; 742a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPanOffset = 0.0f; 743a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal gPanViewfinder = true; 744a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 745a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gThisH1t); 746a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal db_Identity3x3(gLastH1t); 74741a2e9735136f372de95652d0828600282c8e967mbansal } 748a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal 74941a2e9735136f372de95652d0828600282c8e967mbansal gWarpImage = (bool)flag; 750eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 751eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 752eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 753eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansalJNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( 754eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal JNIEnv * env, jobject obj) 755eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal{ 756eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal for(int i=0; i<16; i++) 757eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal { 758eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal g_dAffinetransGL[i] = g_dAffinetrans[i]; 759a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal g_dAffinetransPanGL[i] = g_dAffinetransPan[i]; 760a6f0b9e759fa2d19d493bde7ffa8105ec2978b94mbansal g_dTranslationToFBOCenterGL[i] = g_dTranslationToFBOCenter[i]; 761eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal } 762eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal} 763