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