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