mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 1 | // OpenGL ES 2.0 code |
| 2 | #include <jni.h> |
| 3 | #include <android/log.h> |
| 4 | |
| 5 | #include <db_utilities_camera.h> |
| 6 | #include "mosaic/ImageUtils.h" |
| 7 | #include "mosaic_renderer/FrameBuffer.h" |
| 8 | #include "mosaic_renderer/WarpRenderer.h" |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 9 | #include "mosaic_renderer/SurfaceTextureRenderer.h" |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 10 | #include "mosaic_renderer/YVURenderer.h" |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
| 13 | #include <math.h> |
| 14 | |
| 15 | #include "mosaic_renderer_jni.h" |
| 16 | |
| 17 | #define LOG_TAG "MosaicRenderer" |
| 18 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 19 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 20 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) |
| 21 | |
| 22 | // Texture handle |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 23 | GLuint gSurfaceTextureID[1]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 24 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 25 | bool gWarpImage = true; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 26 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 27 | // Low-Res input image frame in YUVA format for preview rendering and processing |
| 28 | // and high-res YUVA input image for processing. |
| 29 | unsigned char* gPreviewImage[NR]; |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 30 | // Low-Res & high-res preview image width |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 31 | int gPreviewImageWidth[NR]; |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 32 | // Low-Res & high-res preview image height |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 33 | int gPreviewImageHeight[NR]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 34 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 35 | // Semaphore to protect simultaneous read/writes from gPreviewImage |
| 36 | sem_t gPreviewImage_semaphore; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 37 | |
| 38 | // Off-screen preview FBO width (large enough to store the entire |
| 39 | // preview mosaic). |
| 40 | int gPreviewFBOWidth; |
| 41 | // Off-screen preview FBO height (large enough to store the entire |
| 42 | // preview mosaic). |
| 43 | int gPreviewFBOHeight; |
| 44 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 45 | // gK is the transformation to map the canonical {-1,1} vertex coordinate system |
| 46 | // to the {0,gPreviewImageWidth[LR]} input image frame coordinate system before |
| 47 | // applying the given affine transformation trs. gKm is the corresponding |
| 48 | // transformation for going to the {0,gPreviewFBOWidth}. |
| 49 | double gK[9]; |
| 50 | double gKinv[9]; |
| 51 | double gKm[9]; |
| 52 | double gKminv[9]; |
| 53 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 54 | // Shader to copy input SurfaceTexture into and RGBA FBO. The two shaders |
| 55 | // render to the textures with dimensions corresponding to the low-res and |
| 56 | // high-res image frames. |
| 57 | SurfaceTextureRenderer gSurfTexRenderer[NR]; |
| 58 | // Off-screen FBOs to store the low-res and high-res RGBA copied out from |
| 59 | // the SurfaceTexture by the gSurfTexRenderers. |
| 60 | FrameBuffer gBufferInput[NR]; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 61 | |
| 62 | // Shader to convert RGBA textures into YVU textures for processing |
| 63 | YVURenderer gYVURenderer[NR]; |
| 64 | // Off-screen FBOs to store the low-res and high-res YVU textures for processing |
| 65 | FrameBuffer gBufferInputYVU[NR]; |
| 66 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 67 | // Shader to add warped current frame to the preview FBO |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 68 | WarpRenderer gWarper1; |
| 69 | // Shader to translate the preview FBO |
| 70 | WarpRenderer gWarper2; |
| 71 | // Off-screen FBOs (flip-flop) to store the result of gWarper1 & gWarper2 |
| 72 | FrameBuffer gBuffer[2]; |
| 73 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 74 | // Shader to warp and render the preview FBO to the screen |
| 75 | WarpRenderer gPreview; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 76 | |
| 77 | // Index of the gBuffer FBO gWarper1 is going to write into |
| 78 | int gCurrentFBOIndex = 0; |
| 79 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 80 | // 3x3 Matrices holding the transformation of this frame (gThisH1t) and of |
| 81 | // the last frame (gLastH1t) w.r.t the first frame. |
| 82 | double gThisH1t[9]; |
| 83 | double gLastH1t[9]; |
| 84 | |
| 85 | // Variables to represent the fixed position of the top-left corner of the |
| 86 | // current frame in the previewFBO |
| 87 | double gCenterOffsetX = 0.0f; |
| 88 | double gCenterOffsetY = 0.0f; |
| 89 | |
| 90 | // X-Offset of the viewfinder (current frame) w.r.t |
| 91 | // (gCenterOffsetX, gCenterOffsetY). This offset varies with time and is |
| 92 | // used to pan the viewfinder across the UI layout. |
| 93 | double gPanOffset = 0.0f; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 94 | |
| 95 | // Variables tracking the translation value for the current frame and the |
| 96 | // last frame (both w.r.t the first frame). The difference between these |
| 97 | // values is used to control the panning speed of the viewfinder display |
| 98 | // on the UI screen. |
| 99 | double gThisTx = 0.0f; |
| 100 | double gLastTx = 0.0f; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 101 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 102 | // These are the scale factors used by the gPreview shader to ensure that |
| 103 | // the image frame is correctly scaled to the full UI layout height while |
| 104 | // maintaining its aspect ratio |
| 105 | double gUILayoutScalingX = 1.0f; |
| 106 | double gUILayoutScalingY = 1.0f; |
| 107 | |
| 108 | // State of the viewfinder. Set to false when the viewfinder hits the UI edge. |
| 109 | bool gPanViewfinder = true; |
| 110 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 111 | // Affine transformation in GL 4x4 format (column-major) to warp the |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 112 | // last frame mosaic into the current frame coordinate system. |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 113 | GLfloat g_dAffinetransGL[16]; |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 114 | double g_dAffinetrans[16]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 115 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 116 | // Affine transformation in GL 4x4 format (column-major) to translate the |
| 117 | // preview FBO across the screen (viewfinder panning). |
| 118 | GLfloat g_dAffinetransPanGL[16]; |
| 119 | double g_dAffinetransPan[16]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 120 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 121 | // XY translation in GL 4x4 format (column-major) to center the current |
| 122 | // preview mosaic in the preview FBO |
| 123 | GLfloat g_dTranslationToFBOCenterGL[16]; |
| 124 | double g_dTranslationToFBOCenter[16]; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 125 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 126 | // GL 4x4 Identity transformation |
| 127 | GLfloat g_dAffinetransIdent[] = { |
| 128 | 1., 0., 0., 0., |
| 129 | 0., 1., 0., 0., |
| 130 | 0., 0., 1., 0., |
| 131 | 0., 0., 0., 1.}; |
| 132 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 133 | float g_dIdent3x3[] = { |
| 134 | 1.0, 0.0, 0.0, |
| 135 | 0.0, 1.0, 0.0, |
| 136 | 0.0, 0.0, 1.0}; |
| 137 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 138 | const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 139 | |
| 140 | static void printGLString(const char *name, GLenum s) { |
| 141 | const char *v = (const char *) glGetString(s); |
| 142 | LOGI("GL %s = %s\n", name, v); |
| 143 | } |
| 144 | |
| 145 | // @return false if there was an error |
| 146 | bool checkGlError(const char* op) { |
| 147 | GLint error = glGetError(); |
| 148 | if (error != 0) { |
| 149 | LOGE("after %s() glError (0x%x)\n", op, error); |
| 150 | return false; |
| 151 | } |
| 152 | return true; |
| 153 | } |
| 154 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 155 | void bindSurfaceTexture(GLuint texId) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 156 | { |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 157 | glBindTexture(GL_TEXTURE_EXTERNAL_OES_ENUM, texId); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 158 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 159 | // Can't do mipmapping with camera source |
| 160 | glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MIN_FILTER, |
| 161 | GL_LINEAR); |
| 162 | glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MAG_FILTER, |
| 163 | GL_LINEAR); |
| 164 | // Clamp to edge is the only option |
| 165 | glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_S, |
| 166 | GL_CLAMP_TO_EDGE); |
| 167 | glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_T, |
| 168 | GL_CLAMP_TO_EDGE); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 169 | } |
| 170 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 171 | void ClearPreviewImage(int mID) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 172 | { |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 173 | unsigned char* ptr = gPreviewImage[mID]; |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 174 | for(int j = 0, i = 0; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 175 | j < gPreviewImageWidth[mID] * gPreviewImageHeight[mID] * 4; |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 176 | j += 4) |
| 177 | { |
| 178 | ptr[i++] = 0; |
| 179 | ptr[i++] = 0; |
| 180 | ptr[i++] = 0; |
| 181 | ptr[i++] = 255; |
| 182 | } |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 183 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | void ConvertAffine3x3toGL4x4(double *matGL44, double *mat33) |
| 187 | { |
| 188 | matGL44[0] = mat33[0]; |
| 189 | matGL44[1] = mat33[3]; |
| 190 | matGL44[2] = 0.0; |
| 191 | matGL44[3] = mat33[6]; |
| 192 | |
| 193 | matGL44[4] = mat33[1]; |
| 194 | matGL44[5] = mat33[4]; |
| 195 | matGL44[6] = 0.0; |
| 196 | matGL44[7] = mat33[7]; |
| 197 | |
| 198 | matGL44[8] = 0; |
| 199 | matGL44[9] = 0; |
| 200 | matGL44[10] = 1.0; |
| 201 | matGL44[11] = 0.0; |
| 202 | |
| 203 | matGL44[12] = mat33[2]; |
| 204 | matGL44[13] = mat33[5]; |
| 205 | matGL44[14] = 0.0; |
| 206 | matGL44[15] = mat33[8]; |
| 207 | } |
| 208 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 209 | // This function computes fills the 4x4 matrices g_dAffinetrans, |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 210 | // and g_dAffinetransPan using the specified 3x3 affine |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 211 | // transformation between the first captured frame and the current frame. |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 212 | // The computed g_dAffinetrans is such that it warps the preview mosaic in |
| 213 | // the last frame's coordinate system into the coordinate system of the |
| 214 | // current frame. Thus, applying this transformation will create the current |
| 215 | // frame mosaic but with the current frame missing. This frame will then be |
| 216 | // pasted in by gWarper2 after translating it by g_dTranslationToFBOCenter. |
| 217 | // The computed g_dAffinetransPan is such that it offsets the computed preview |
| 218 | // mosaic horizontally to make the viewfinder pan within the UI layout. |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 219 | void UpdateWarpTransformation(float *trs) |
| 220 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 221 | double H[9], Hp[9], Htemp1[9], Htemp2[9], T[9]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 222 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 223 | for(int i = 0; i < 9; i++) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 224 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 225 | gThisH1t[i] = trs[i]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 226 | } |
| 227 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 228 | db_Identity3x3(T); |
| 229 | T[2] = -gCenterOffsetX; |
| 230 | T[5] = -gCenterOffsetY; |
| 231 | |
| 232 | // H = ( inv(gThisH1t) * gLastH1t ) * T |
| 233 | db_Identity3x3(Htemp1); |
| 234 | db_Identity3x3(Htemp2); |
| 235 | db_Identity3x3(H); |
| 236 | db_InvertAffineTransform(Htemp1, gThisH1t); |
| 237 | db_Multiply3x3_3x3(Htemp2, Htemp1, gLastH1t); |
| 238 | db_Multiply3x3_3x3(H, Htemp2, T); |
| 239 | |
| 240 | for(int i = 0; i < 9; i++) |
| 241 | { |
| 242 | gLastH1t[i] = gThisH1t[i]; |
| 243 | } |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 244 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 245 | // Move the origin such that the frame is centered in the previewFBO |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 246 | // i.e. H = inv(T) * H |
| 247 | H[2] += gCenterOffsetX; |
| 248 | H[5] += gCenterOffsetY; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 249 | |
| 250 | // Hp = inv(K) * H * K |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 251 | // K moves the coordinate system from openGL to image pixels so |
| 252 | // that the alignment transform H can be applied to them. |
| 253 | // inv(K) moves the coordinate system back to openGL normalized |
| 254 | // coordinates so that the shader can correctly render it. |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 255 | db_Identity3x3(Htemp1); |
| 256 | db_Multiply3x3_3x3(Htemp1, H, gKm); |
| 257 | db_Multiply3x3_3x3(Hp, gKminv, Htemp1); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 258 | |
| 259 | ConvertAffine3x3toGL4x4(g_dAffinetrans, Hp); |
| 260 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 261 | //////////////////////////////////////////////// |
| 262 | ////// Compute g_dAffinetransPan now... ////// |
| 263 | //////////////////////////////////////////////// |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 264 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 265 | gThisTx = trs[2]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 266 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 267 | if(gPanViewfinder) |
| 268 | { |
| 269 | gPanOffset += (gThisTx - gLastTx) * VIEWFINDER_PAN_FACTOR_HORZ; |
| 270 | } |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 271 | |
| 272 | gLastTx = gThisTx; |
| 273 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 274 | // Compute the position of the current frame in the screen coordinate system |
| 275 | // and stop the viewfinder panning if we hit the maximum border allowed for |
| 276 | // this UI layout |
| 277 | double normalizedXPositionOnScreenLeft = (2 * |
| 278 | (gCenterOffsetX + gPanOffset) / gPreviewFBOWidth - 1.0) * |
| 279 | gUILayoutScalingX; |
| 280 | double normalizedScreenLimitLeft = -1.0 + VIEWPORT_BORDER_FACTOR_HORZ * 2.0; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 281 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 282 | double normalizedXPositionOnScreenRight = (2 * |
| 283 | ((gCenterOffsetX + gPanOffset) + gPreviewImageWidth[LR]) / |
| 284 | gPreviewFBOWidth - 1.0) * gUILayoutScalingX; |
| 285 | double normalizedScreenLimitRight = 1.0 - VIEWPORT_BORDER_FACTOR_HORZ * 2.0; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 286 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 287 | if(normalizedXPositionOnScreenRight > normalizedScreenLimitRight || |
| 288 | normalizedXPositionOnScreenLeft < normalizedScreenLimitLeft) |
| 289 | gPanViewfinder = false; |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 290 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 291 | db_Identity3x3(H); |
| 292 | H[2] = gPanOffset; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 293 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 294 | // Hp = inv(K) * H * K |
| 295 | db_Identity3x3(Htemp1); |
| 296 | db_Multiply3x3_3x3(Htemp1, H, gKm); |
| 297 | db_Multiply3x3_3x3(Hp, gKminv, Htemp1); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 298 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 299 | ConvertAffine3x3toGL4x4(g_dAffinetransPan, Hp); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 300 | } |
| 301 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 302 | void AllocateTextureMemory(int widthHR, int heightHR, int widthLR, int heightLR) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 303 | { |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 304 | gPreviewImageWidth[HR] = widthHR; |
| 305 | gPreviewImageHeight[HR] = heightHR; |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 306 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 307 | gPreviewImageWidth[LR] = widthLR; |
| 308 | gPreviewImageHeight[LR] = heightLR; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 309 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 310 | sem_init(&gPreviewImage_semaphore, 0, 1); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 311 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 312 | sem_wait(&gPreviewImage_semaphore); |
| 313 | gPreviewImage[LR] = ImageUtils::allocateImage(gPreviewImageWidth[LR], |
| 314 | gPreviewImageHeight[LR], 4); |
| 315 | ClearPreviewImage(LR); |
| 316 | gPreviewImage[HR] = ImageUtils::allocateImage(gPreviewImageWidth[HR], |
| 317 | gPreviewImageHeight[HR], 4); |
| 318 | ClearPreviewImage(HR); |
| 319 | sem_post(&gPreviewImage_semaphore); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 320 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 321 | gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR]; |
| 322 | gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 323 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 324 | // The origin is such that the current frame will sit with its center |
| 325 | // at the center of the previewFBO |
| 326 | gCenterOffsetX = (gPreviewFBOWidth / 2 - gPreviewImageWidth[LR] / 2); |
| 327 | gCenterOffsetY = (gPreviewFBOHeight / 2 - gPreviewImageHeight[LR] / 2); |
| 328 | |
| 329 | gPanOffset = 0.0f; |
| 330 | |
| 331 | db_Identity3x3(gThisH1t); |
| 332 | db_Identity3x3(gLastH1t); |
| 333 | |
| 334 | gPanViewfinder = true; |
| 335 | |
| 336 | int w = gPreviewImageWidth[LR]; |
| 337 | int h = gPreviewImageHeight[LR]; |
| 338 | |
| 339 | int wm = gPreviewFBOWidth; |
| 340 | int hm = gPreviewFBOHeight; |
| 341 | |
| 342 | // K is the transformation to map the canonical [-1,1] vertex coordinate |
| 343 | // system to the [0,w] image coordinate system before applying the given |
| 344 | // affine transformation trs. |
| 345 | gKm[0] = wm / 2.0 - 0.5; |
| 346 | gKm[1] = 0.0; |
| 347 | gKm[2] = wm / 2.0 - 0.5; |
| 348 | gKm[3] = 0.0; |
| 349 | gKm[4] = hm / 2.0 - 0.5; |
| 350 | gKm[5] = hm / 2.0 - 0.5; |
| 351 | gKm[6] = 0.0; |
| 352 | gKm[7] = 0.0; |
| 353 | gKm[8] = 1.0; |
| 354 | |
| 355 | gK[0] = w / 2.0 - 0.5; |
| 356 | gK[1] = 0.0; |
| 357 | gK[2] = w / 2.0 - 0.5; |
| 358 | gK[3] = 0.0; |
| 359 | gK[4] = h / 2.0 - 0.5; |
| 360 | gK[5] = h / 2.0 - 0.5; |
| 361 | gK[6] = 0.0; |
| 362 | gK[7] = 0.0; |
| 363 | gK[8] = 1.0; |
| 364 | |
| 365 | db_Identity3x3(gKinv); |
| 366 | db_InvertCalibrationMatrix(gKinv, gK); |
| 367 | |
| 368 | db_Identity3x3(gKminv); |
| 369 | db_InvertCalibrationMatrix(gKminv, gKm); |
| 370 | |
| 371 | ////////////////////////////////////////// |
| 372 | ////// Compute g_Translation now... ////// |
| 373 | ////////////////////////////////////////// |
| 374 | double T[9], Tp[9], Ttemp[9]; |
| 375 | |
| 376 | db_Identity3x3(T); |
| 377 | T[2] = gCenterOffsetX; |
| 378 | T[5] = gCenterOffsetY; |
| 379 | |
| 380 | // Tp = inv(K) * T * K |
| 381 | db_Identity3x3(Ttemp); |
| 382 | db_Multiply3x3_3x3(Ttemp, T, gK); |
| 383 | db_Multiply3x3_3x3(Tp, gKinv, Ttemp); |
| 384 | |
| 385 | ConvertAffine3x3toGL4x4(g_dTranslationToFBOCenter, Tp); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 386 | |
| 387 | UpdateWarpTransformation(g_dIdent3x3); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 388 | } |
| 389 | |
| 390 | void FreeTextureMemory() |
| 391 | { |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 392 | sem_wait(&gPreviewImage_semaphore); |
| 393 | ImageUtils::freeImage(gPreviewImage[LR]); |
| 394 | ImageUtils::freeImage(gPreviewImage[HR]); |
| 395 | sem_post(&gPreviewImage_semaphore); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 396 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 397 | sem_destroy(&gPreviewImage_semaphore); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 398 | } |
| 399 | |
| 400 | extern "C" |
| 401 | { |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 402 | JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 403 | JNIEnv * env, jobject obj); |
| 404 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( |
| 405 | JNIEnv * env, jobject obj, jint width, jint height); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 406 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( |
| 407 | JNIEnv * env, jobject obj, jfloatArray stMatrix); |
| 408 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( |
| 409 | JNIEnv * env, jobject obj); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 410 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( |
| 411 | JNIEnv * env, jobject obj); |
| 412 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( |
| 413 | JNIEnv * env, jobject obj); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 414 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( |
| 415 | JNIEnv * env, jobject obj, jboolean flag); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 416 | }; |
| 417 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 418 | JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init( |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 419 | JNIEnv * env, jobject obj) |
| 420 | { |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 421 | gSurfTexRenderer[LR].InitializeGLProgram(); |
| 422 | gSurfTexRenderer[HR].InitializeGLProgram(); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 423 | gYVURenderer[LR].InitializeGLProgram(); |
| 424 | gYVURenderer[HR].InitializeGLProgram(); |
| 425 | gWarper1.InitializeGLProgram(); |
| 426 | gWarper2.InitializeGLProgram(); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 427 | gPreview.InitializeGLProgram(); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 428 | gBuffer[0].InitializeGLContext(); |
| 429 | gBuffer[1].InitializeGLContext(); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 430 | gBufferInput[LR].InitializeGLContext(); |
| 431 | gBufferInput[HR].InitializeGLContext(); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 432 | gBufferInputYVU[LR].InitializeGLContext(); |
| 433 | gBufferInputYVU[HR].InitializeGLContext(); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 434 | |
| 435 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 436 | |
| 437 | glGenTextures(1, gSurfaceTextureID); |
| 438 | // bind the surface texture |
| 439 | bindSurfaceTexture(gSurfaceTextureID[0]); |
| 440 | |
| 441 | return (jint) gSurfaceTextureID[0]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 442 | } |
| 443 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 444 | |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 445 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset( |
| 446 | JNIEnv * env, jobject obj, jint width, jint height) |
| 447 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 448 | gUILayoutScalingX = (PREVIEW_FBO_WIDTH_SCALE / PREVIEW_FBO_HEIGHT_SCALE) * |
| 449 | (gPreviewImageWidth[LR] / gPreviewImageHeight[LR]) / (width / height) * |
| 450 | PREVIEW_FBO_HEIGHT_SCALE; |
| 451 | gUILayoutScalingY = PREVIEW_FBO_HEIGHT_SCALE; |
| 452 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 453 | gBuffer[0].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); |
| 454 | gBuffer[1].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 455 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 456 | gBufferInput[LR].Init(gPreviewImageWidth[LR], |
| 457 | gPreviewImageHeight[LR], GL_RGBA); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 458 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 459 | gBufferInput[HR].Init(gPreviewImageWidth[HR], |
| 460 | gPreviewImageHeight[HR], GL_RGBA); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 461 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 462 | gBufferInputYVU[LR].Init(gPreviewImageWidth[LR], |
| 463 | gPreviewImageHeight[LR], GL_RGBA); |
| 464 | |
| 465 | gBufferInputYVU[HR].Init(gPreviewImageWidth[HR], |
| 466 | gPreviewImageHeight[HR], GL_RGBA); |
| 467 | |
| 468 | sem_wait(&gPreviewImage_semaphore); |
| 469 | ClearPreviewImage(LR); |
| 470 | ClearPreviewImage(HR); |
| 471 | sem_post(&gPreviewImage_semaphore); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 472 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 473 | // bind the surface texture |
| 474 | bindSurfaceTexture(gSurfaceTextureID[0]); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 475 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 476 | gSurfTexRenderer[LR].SetupGraphics(&gBufferInput[LR]); |
| 477 | gSurfTexRenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); |
| 478 | gSurfTexRenderer[LR].SetViewportMatrix(1, 1, 1, 1); |
| 479 | gSurfTexRenderer[LR].SetScalingMatrix(1.0f, -1.0f); |
| 480 | gSurfTexRenderer[LR].SetInputTextureName(gSurfaceTextureID[0]); |
| 481 | gSurfTexRenderer[LR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); |
| 482 | |
| 483 | gSurfTexRenderer[HR].SetupGraphics(&gBufferInput[HR]); |
| 484 | gSurfTexRenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); |
| 485 | gSurfTexRenderer[HR].SetViewportMatrix(1, 1, 1, 1); |
| 486 | gSurfTexRenderer[HR].SetScalingMatrix(1.0f, -1.0f); |
| 487 | gSurfTexRenderer[HR].SetInputTextureName(gSurfaceTextureID[0]); |
| 488 | gSurfTexRenderer[HR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM); |
| 489 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 490 | gYVURenderer[LR].SetupGraphics(&gBufferInputYVU[LR]); |
| 491 | gYVURenderer[LR].Clear(0.0, 0.0, 0.0, 1.0); |
| 492 | gYVURenderer[LR].SetInputTextureName(gBufferInput[LR].GetTextureName()); |
| 493 | gYVURenderer[LR].SetInputTextureType(GL_TEXTURE_2D); |
| 494 | |
| 495 | gYVURenderer[HR].SetupGraphics(&gBufferInputYVU[HR]); |
| 496 | gYVURenderer[HR].Clear(0.0, 0.0, 0.0, 1.0); |
| 497 | gYVURenderer[HR].SetInputTextureName(gBufferInput[HR].GetTextureName()); |
| 498 | gYVURenderer[HR].SetInputTextureType(GL_TEXTURE_2D); |
| 499 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 500 | // gBuffer[1-gCurrentFBOIndex] --> gWarper1 --> gBuffer[gCurrentFBOIndex] |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 501 | gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); |
| 502 | gWarper1.Clear(0.0, 0.0, 0.0, 1.0); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 503 | gWarper1.SetViewportMatrix(1, 1, 1, 1); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 504 | gWarper1.SetScalingMatrix(1.0f, 1.0f); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 505 | gWarper1.SetInputTextureName(gBuffer[1 - gCurrentFBOIndex].GetTextureName()); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 506 | gWarper1.SetInputTextureType(GL_TEXTURE_2D); |
| 507 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 508 | // gBufferInput[LR] --> gWarper2 --> gBuffer[gCurrentFBOIndex] |
| 509 | gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 510 | gWarper2.Clear(0.0, 0.0, 0.0, 1.0); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 511 | gWarper2.SetViewportMatrix(gPreviewImageWidth[LR], |
| 512 | gPreviewImageHeight[LR], gBuffer[gCurrentFBOIndex].GetWidth(), |
| 513 | gBuffer[gCurrentFBOIndex].GetHeight()); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 514 | gWarper2.SetScalingMatrix(1.0f, 1.0f); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 515 | gWarper2.SetInputTextureName(gBufferInput[LR].GetTextureName()); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 516 | gWarper2.SetInputTextureType(GL_TEXTURE_2D); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 517 | |
| 518 | gPreview.SetupGraphics(width, height); |
| 519 | gPreview.Clear(0.0, 0.0, 0.0, 1.0); |
| 520 | gPreview.SetViewportMatrix(1, 1, 1, 1); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 521 | // Scale the previewFBO so that the viewfinder window fills the layout height |
| 522 | // while maintaining the image aspect ratio |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 523 | gPreview.SetScalingMatrix(gUILayoutScalingX, -1.0f * gUILayoutScalingY); |
| 524 | gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 525 | gPreview.SetInputTextureType(GL_TEXTURE_2D); |
| 526 | } |
| 527 | |
| 528 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess( |
| 529 | JNIEnv * env, jobject obj, jfloatArray stMatrix) |
| 530 | { |
| 531 | jfloat *stmat = env->GetFloatArrayElements(stMatrix, 0); |
| 532 | |
| 533 | gSurfTexRenderer[LR].SetSTMatrix((float*) stmat); |
| 534 | gSurfTexRenderer[HR].SetSTMatrix((float*) stmat); |
| 535 | |
| 536 | env->ReleaseFloatArrayElements(stMatrix, stmat, 0); |
| 537 | |
| 538 | gSurfTexRenderer[LR].DrawTexture(g_dAffinetransIdent); |
| 539 | gSurfTexRenderer[HR].DrawTexture(g_dAffinetransIdent); |
| 540 | } |
| 541 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 542 | #ifndef now_ms |
| 543 | #include <time.h> |
| 544 | static double |
| 545 | now_ms(void) |
| 546 | { |
| 547 | //struct timespec res; |
| 548 | struct timeval res; |
| 549 | //clock_gettime(CLOCK_REALTIME, &res); |
| 550 | gettimeofday(&res, NULL); |
| 551 | return 1000.0*res.tv_sec + (double)res.tv_usec/1e3; |
| 552 | } |
| 553 | #endif |
| 554 | |
| 555 | |
| 556 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 557 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU( |
| 558 | JNIEnv * env, jobject obj) |
| 559 | { |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 560 | double t0, t1, time_c; |
| 561 | |
| 562 | t0 = now_ms(); |
| 563 | |
| 564 | gYVURenderer[LR].DrawTexture(); |
| 565 | gYVURenderer[HR].DrawTexture(); |
| 566 | |
| 567 | t1 = now_ms(); |
| 568 | time_c = t1 - t0; |
| 569 | LOGV("YVU Rendering: %g ms", time_c); |
| 570 | |
| 571 | sem_wait(&gPreviewImage_semaphore); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 572 | // Bind to the input LR FBO and read the Low-Res data from there... |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 573 | glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[LR].GetFrameBufferName()); |
| 574 | t0 = now_ms(); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 575 | glReadPixels(0, |
| 576 | 0, |
| 577 | gBufferInput[LR].GetWidth(), |
| 578 | gBufferInput[LR].GetHeight(), |
| 579 | GL_RGBA, |
| 580 | GL_UNSIGNED_BYTE, |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 581 | gPreviewImage[LR]); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 582 | |
| 583 | checkGlError("glReadPixels LR"); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 584 | t1 = now_ms(); |
| 585 | time_c = t1 - t0; |
| 586 | LOGV("glReadPixels LR: %g ms", time_c); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 587 | |
| 588 | // Bind to the input HR FBO and read the high-res data from there... |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 589 | glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[HR].GetFrameBufferName()); |
| 590 | t0 = now_ms(); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 591 | glReadPixels(0, |
| 592 | 0, |
| 593 | gBufferInput[HR].GetWidth(), |
| 594 | gBufferInput[HR].GetHeight(), |
| 595 | GL_RGBA, |
| 596 | GL_UNSIGNED_BYTE, |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 597 | gPreviewImage[HR]); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 598 | |
| 599 | checkGlError("glReadPixels HR"); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 600 | t1 = now_ms(); |
| 601 | time_c = t1 - t0; |
| 602 | LOGV("glReadPixels HR: %g ms", time_c); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 603 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 604 | sem_post(&gPreviewImage_semaphore); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 605 | } |
| 606 | |
| 607 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step( |
| 608 | JNIEnv * env, jobject obj) |
| 609 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 610 | if(!gWarpImage) // ViewFinder |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 611 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 612 | gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 613 | gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 614 | |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 615 | gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); |
| 616 | gPreview.DrawTexture(g_dAffinetransIdent); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 617 | } |
| 618 | else |
| 619 | { |
| 620 | gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 621 | // Clear the destination so that we can paint on it afresh |
| 622 | gWarper1.Clear(0.0, 0.0, 0.0, 1.0); |
| 623 | gWarper1.SetInputTextureName( |
| 624 | gBuffer[1 - gCurrentFBOIndex].GetTextureName()); |
| 625 | gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]); |
| 626 | gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName()); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 627 | |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 628 | gWarper1.DrawTexture(g_dAffinetransGL); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 629 | gWarper2.DrawTexture(g_dTranslationToFBOCenterGL); |
| 630 | gPreview.DrawTexture(g_dAffinetransPanGL); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 631 | |
| 632 | gCurrentFBOIndex = 1 - gCurrentFBOIndex; |
| 633 | } |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 634 | } |
| 635 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 636 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping( |
| 637 | JNIEnv * env, jobject obj, jboolean flag) |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 638 | { |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 639 | // TODO: Review this logic |
| 640 | if(gWarpImage != (bool) flag) //switching from viewfinder to capture or vice-versa |
| 641 | { |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 642 | // Clear gBuffer[0] |
| 643 | gWarper1.SetupGraphics(&gBuffer[0]); |
mbansal | 1e762b1 | 2011-08-16 10:01:20 -0400 | [diff] [blame] | 644 | gWarper1.Clear(0.0, 0.0, 0.0, 1.0); |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 645 | // Clear gBuffer[1] |
| 646 | gWarper1.SetupGraphics(&gBuffer[1]); |
| 647 | gWarper1.Clear(0.0, 0.0, 0.0, 1.0); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 648 | // Clear the screen to black. |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 649 | gPreview.Clear(0.0, 0.0, 0.0, 1.0); |
| 650 | |
| 651 | gLastTx = 0.0f; |
| 652 | gPanOffset = 0.0f; |
| 653 | gPanViewfinder = true; |
| 654 | |
| 655 | db_Identity3x3(gThisH1t); |
| 656 | db_Identity3x3(gLastH1t); |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 657 | } |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 658 | |
mbansal | 41a2e97 | 2011-08-08 20:23:02 -0400 | [diff] [blame] | 659 | gWarpImage = (bool)flag; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 660 | } |
| 661 | |
| 662 | |
| 663 | JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready( |
| 664 | JNIEnv * env, jobject obj) |
| 665 | { |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 666 | for(int i=0; i<16; i++) |
| 667 | { |
| 668 | g_dAffinetransGL[i] = g_dAffinetrans[i]; |
mbansal | a6f0b9e | 2011-08-19 10:18:54 -0400 | [diff] [blame] | 669 | g_dAffinetransPanGL[i] = g_dAffinetransPan[i]; |
| 670 | g_dTranslationToFBOCenterGL[i] = g_dTranslationToFBOCenter[i]; |
mbansal | eeb94d4 | 2011-08-02 11:31:28 -0400 | [diff] [blame] | 671 | } |
| 672 | } |