summaryrefslogtreecommitdiffstats
path: root/jni/mosaic_renderer_jni.cpp
diff options
context:
space:
mode:
authormbansal <mayank.bansal@sri.com>2011-08-16 10:01:20 -0400
committerWei-Ta Chen <weita@google.com>2011-08-18 14:39:33 -0700
commit1e762b1f935c9d4a06af6dd56121590ca81d48b1 (patch)
treeb7177cb69ece87e1d55f587779a53f213255592d /jni/mosaic_renderer_jni.cpp
parent362928c00ad4ecc0466c353d942c6d6c7cc5f5ee (diff)
downloadLegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.zip
LegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.tar.gz
LegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.tar.bz2
Updates to allow the viewfinder to slide across the UI with device panning. Also, rendering updates for color conversion using GPU.
1) Refactored the SurfaceTextureRenderer and WarpRenderer classes to inherit from a new base class Renderer. 2) Fixed a minor bug in the Blend class and added a helper function to create the mosaic in middle frame coordinate system [no changes in run-time behavior]. 3) Added a flip-flop gPreviewFBO to allow panning the viewfinder across the UI when the user pans the device. 4) Fixed the size of the viewfinder and preview mosaic to match the UI layout height. 5) The viewfinder in the preview stage is now aligned with the viewfinder in the capture stage. 6) Added new class YVURenderer that converts from RGB to YVU data using GLSL shaders. 7) Modified the rendering pipeline to use GPU for RGB to YVU conversion. The processing thread now only performs conversion from YVUA interlaced to YVU planar format. 8) Updates following Wei-Ta's code-review comments. Change-Id: I6c18df3b57d1c2d78d55da8a8f3b9cd970c8d903
Diffstat (limited to 'jni/mosaic_renderer_jni.cpp')
-rw-r--r--jni/mosaic_renderer_jni.cpp356
1 files changed, 258 insertions, 98 deletions
diff --git a/jni/mosaic_renderer_jni.cpp b/jni/mosaic_renderer_jni.cpp
index c7e11b0..b58e529 100644
--- a/jni/mosaic_renderer_jni.cpp
+++ b/jni/mosaic_renderer_jni.cpp
@@ -7,6 +7,7 @@
#include "mosaic_renderer/FrameBuffer.h"
#include "mosaic_renderer/WarpRenderer.h"
#include "mosaic_renderer/SurfaceTextureRenderer.h"
+#include "mosaic_renderer/YVURenderer.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
@@ -23,17 +24,16 @@ GLuint gSurfaceTextureID[1];
bool gWarpImage = true;
-// Low-Res input image frame in RGB format for preview rendering and processing
-// and high-res RGB input image for processing.
-unsigned char* gPreviewImageRGB[NR];
+// Low-Res input image frame in YUVA format for preview rendering and processing
+// and high-res YUVA input image for processing.
+unsigned char* gPreviewImage[NR];
// Low-Res & high-res preview image width
-int gPreviewImageRGBWidth[NR];
+int gPreviewImageWidth[NR];
// Low-Res & high-res preview image height
-int gPreviewImageRGBHeight[NR];
+int gPreviewImageHeight[NR];
-// Semaphore to protect simultaneous read/writes from gPreviewImageRGB
-sem_t gPreviewImageRGB_semaphore;
-sem_t gPreviewImageReady_semaphore;
+// Semaphore to protect simultaneous read/writes from gPreviewImage
+sem_t gPreviewImage_semaphore;
// Off-screen preview FBO width (large enough to store the entire
// preview mosaic).
@@ -49,12 +49,36 @@ SurfaceTextureRenderer gSurfTexRenderer[NR];
// Off-screen FBOs to store the low-res and high-res RGBA copied out from
// the SurfaceTexture by the gSurfTexRenderers.
FrameBuffer gBufferInput[NR];
+
+// Shader to convert RGBA textures into YVU textures for processing
+YVURenderer gYVURenderer[NR];
+// Off-screen FBOs to store the low-res and high-res YVU textures for processing
+FrameBuffer gBufferInputYVU[NR];
+
// Shader to add warped current frame to the preview FBO
-WarpRenderer gWarper;
+WarpRenderer gWarper1;
+// Shader to translate the preview FBO
+WarpRenderer gWarper2;
+// Off-screen FBOs (flip-flop) to store the result of gWarper1 & gWarper2
+FrameBuffer gBuffer[2];
+
// Shader to warp and render the preview FBO to the screen
WarpRenderer gPreview;
-// Off-screen FBO to store the result of gWarper
-FrameBuffer gBuffer;
+
+// Index of the gBuffer FBO gWarper1 is going to write into
+int gCurrentFBOIndex = 0;
+
+// Variables to represent the present top-left corner of the first frame
+// in the previewFBO
+double gOriginX = 0.0f;
+double gOriginY = 0.0f;
+
+// Variables tracking the translation value for the current frame and the
+// last frame (both w.r.t the first frame). The difference between these
+// values is used to control the panning speed of the viewfinder display
+// on the UI screen.
+double gThisTx = 0.0f;
+double gLastTx = 0.0f;
// Affine transformation in GL 4x4 format (column-major) to warp the
// current frame into the first frame coordinate system.
@@ -64,6 +88,10 @@ GLfloat g_dAffinetransGL[16];
// preview FBO into the current frame coordinate system.
GLfloat g_dAffinetransInvGL[16];
+// XY translation in GL 4x4 format (column-major) to slide the preview
+// viewfinder across the preview FBO
+GLfloat g_dTranslationGL[16];
+
// GL 4x4 Identity transformation
GLfloat g_dAffinetransIdent[] = {
1., 0., 0., 0.,
@@ -71,6 +99,11 @@ GLfloat g_dAffinetransIdent[] = {
0., 0., 1., 0.,
0., 0., 0., 1.};
+float g_dIdent3x3[] = {
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0};
+
const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65;
static void printGLString(const char *name, GLenum s) {
@@ -104,11 +137,11 @@ void bindSurfaceTexture(GLuint texId)
GL_CLAMP_TO_EDGE);
}
-void ClearPreviewImageRGB(int mID)
+void ClearPreviewImage(int mID)
{
- unsigned char* ptr = gPreviewImageRGB[mID];
+ unsigned char* ptr = gPreviewImage[mID];
for(int j = 0, i = 0;
- j < gPreviewImageRGBWidth[mID] * gPreviewImageRGBHeight[mID] * 4;
+ j < gPreviewImageWidth[mID] * gPreviewImageHeight[mID] * 4;
j += 4)
{
ptr[i++] = 0;
@@ -142,10 +175,10 @@ void ConvertAffine3x3toGL4x4(double *matGL44, double *mat33)
matGL44[15] = mat33[8];
}
-// This function computes fills the 4x4 matrices g_dAffinetrans and
-// g_dAffinetransInv using the specified 3x3 affine transformation
-// between the first captured frame and the current frame. The computed
-// g_dAffinetrans is such that it warps the current frame into the
+// This function computes fills the 4x4 matrices g_dAffinetrans,
+// g_dAffinetransInv and g_dTranslation using the specified 3x3 affine
+// transformation between the first captured frame and the current frame.
+// The computed g_dAffinetrans is such that it warps the current frame into the
// coordinate system of the first frame. Thus, applying this transformation
// to each successive frame builds up the preview mosaic in the first frame
// coordinate system. Then the computed g_dAffinetransInv is such that it
@@ -155,21 +188,21 @@ void ConvertAffine3x3toGL4x4(double *matGL44, double *mat33)
// mosaic data to still be in alignment with this frame.
void UpdateWarpTransformation(float *trs)
{
- double H[9], Hinv[9], Hp[9], Htemp[9];
+ double H[9], Hinv[9], Hp[9], Htemp[9], T[9], Tp[9], Ttemp[9];
double K[9], Kinv[9];
- int w = gPreviewImageRGBWidth[LR];
- int h = gPreviewImageRGBHeight[LR];
+ int w = gPreviewImageWidth[LR];
+ int h = gPreviewImageHeight[LR];
// K is the transformation to map the canonical [-1,1] vertex coordinate
// system to the [0,w] image coordinate system before applying the given
// affine transformation trs.
- K[0] = w / 2.0;
+ K[0] = w / 2.0 - 0.5;
K[1] = 0.0;
- K[2] = w / 2.0;
+ K[2] = w / 2.0 - 0.5;
K[3] = 0.0;
- K[4] = -h / 2.0;
- K[5] = h / 2.0;
+ K[4] = h / 2.0 - 0.5;
+ K[5] = h / 2.0 - 0.5;
K[6] = 0.0;
K[7] = 0.0;
K[8] = 1.0;
@@ -182,30 +215,36 @@ void UpdateWarpTransformation(float *trs)
H[i] = trs[i];
}
+ gThisTx = trs[2];
+
// Move the origin such that the frame is centered in the previewFBO
- H[2] += (gPreviewFBOWidth / 2 - gPreviewImageRGBWidth[LR] / 2);
- H[5] -= (gPreviewFBOHeight / 2 - gPreviewImageRGBHeight[LR] / 2);
+ H[2] += gOriginX;
+ H[5] += gOriginY;
// Hp = inv(K) * H * K
+ // K moves the coordinate system from openGL to image pixels so
+ // that the alignment transform H can be applied to them.
+ // inv(K) moves the coordinate system back to openGL normalized
+ // coordinates so that the shader can correctly render it.
db_Identity3x3(Htemp);
db_Multiply3x3_3x3(Htemp, H, K);
db_Multiply3x3_3x3(Hp, Kinv, Htemp);
ConvertAffine3x3toGL4x4(g_dAffinetrans, Hp);
- ////////////////////////////////////////////////
- ////// Compute g_dAffinetransInv now... //////
- ////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////
+ ////// Compute g_Translation & g_dAffinetransInv now... //////
+ ////////////////////////////////////////////////////////////////
w = gPreviewFBOWidth;
h = gPreviewFBOHeight;
- K[0] = w / 2.0;
+ K[0] = w / 2.0 - 0.5;
K[1] = 0.0;
- K[2] = w / 2.0;
+ K[2] = w / 2.0 - 0.5;
K[3] = 0.0;
- K[4] = h / 2.0;
- K[5] = h / 2.0;
+ K[4] = h / 2.0 - 0.5;
+ K[5] = h / 2.0 - 0.5;
K[6] = 0.0;
K[7] = 0.0;
K[8] = 1.0;
@@ -213,11 +252,28 @@ void UpdateWarpTransformation(float *trs)
db_Identity3x3(Kinv);
db_InvertCalibrationMatrix(Kinv, K);
+ // T only has a fraction of the x-translation of this frame relative
+ // to the last frame.
+ db_Identity3x3(T);
+ T[2] = (gThisTx - gLastTx) * VIEWFINDER_PAN_FACTOR_HORZ;
+ T[5] = 0;
+
+ gLastTx = gThisTx;
+
db_Identity3x3(Hinv);
db_InvertAffineTransform(Hinv, H);
- Hinv[2] += (gPreviewFBOWidth / 2 - gPreviewImageRGBWidth[LR] / 2);
- Hinv[5] -= (gPreviewFBOHeight / 2 - gPreviewImageRGBHeight[LR] / 2);
+ Hinv[2] += gOriginX;
+ Hinv[5] += gOriginY;
+
+ // We update the origin of where the first frame is laid out in the
+ // previewFBO to reflect that we have panned the entire preview mosaic
+ // inside the previewFBO by translation T. This is needed to ensure
+ // that the next frame can be correctly rendered aligned with the existing
+ // mosaic.
+ gOriginX += T[2];
+ gOriginY += T[5];
+
// Hp = inv(K) * Hinv * K
db_Identity3x3(Htemp);
@@ -225,43 +281,52 @@ void UpdateWarpTransformation(float *trs)
db_Multiply3x3_3x3(Hp, Kinv, Htemp);
ConvertAffine3x3toGL4x4(g_dAffinetransInv, Hp);
+
+ // Tp = inv(K) * T * K
+ db_Identity3x3(Ttemp);
+ db_Multiply3x3_3x3(Ttemp, T, K);
+ db_Multiply3x3_3x3(Tp, Kinv, Ttemp);
+
+ ConvertAffine3x3toGL4x4(g_dTranslation, Tp);
+
}
void AllocateTextureMemory(int widthHR, int heightHR, int widthLR, int heightLR)
{
- gPreviewImageRGBWidth[HR] = widthHR;
- gPreviewImageRGBHeight[HR] = heightHR;
+ gPreviewImageWidth[HR] = widthHR;
+ gPreviewImageHeight[HR] = heightHR;
+
+ gPreviewImageWidth[LR] = widthLR;
+ gPreviewImageHeight[LR] = heightLR;
- gPreviewImageRGBWidth[LR] = widthLR;
- gPreviewImageRGBHeight[LR] = heightLR;
+ sem_init(&gPreviewImage_semaphore, 0, 1);
- sem_init(&gPreviewImageRGB_semaphore, 0, 1);
- sem_init(&gPreviewImageReady_semaphore, 0, 1);
+ sem_wait(&gPreviewImage_semaphore);
+ gPreviewImage[LR] = ImageUtils::allocateImage(gPreviewImageWidth[LR],
+ gPreviewImageHeight[LR], 4);
+ ClearPreviewImage(LR);
+ gPreviewImage[HR] = ImageUtils::allocateImage(gPreviewImageWidth[HR],
+ gPreviewImageHeight[HR], 4);
+ ClearPreviewImage(HR);
+ sem_post(&gPreviewImage_semaphore);
- sem_wait(&gPreviewImageRGB_semaphore);
- gPreviewImageRGB[LR] = ImageUtils::allocateImage(gPreviewImageRGBWidth[LR],
- gPreviewImageRGBHeight[LR], 4);
- ClearPreviewImageRGB(LR);
- gPreviewImageRGB[HR] = ImageUtils::allocateImage(gPreviewImageRGBWidth[HR],
- gPreviewImageRGBHeight[HR], 4);
- ClearPreviewImageRGB(HR);
- sem_post(&gPreviewImageRGB_semaphore);
+ gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR];
+ gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR];
- gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageRGBWidth[LR];
- gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageRGBHeight[LR];
+ gOriginX = (gPreviewFBOWidth / 2 - gPreviewImageWidth[LR] / 2);
+ gOriginY = (gPreviewFBOHeight / 2 - gPreviewImageHeight[LR] / 2);
- UpdateWarpTransformation(g_dAffinetransIdent);
+ UpdateWarpTransformation(g_dIdent3x3);
}
void FreeTextureMemory()
{
- sem_wait(&gPreviewImageRGB_semaphore);
- ImageUtils::freeImage(gPreviewImageRGB[LR]);
- ImageUtils::freeImage(gPreviewImageRGB[HR]);
- sem_post(&gPreviewImageRGB_semaphore);
+ sem_wait(&gPreviewImage_semaphore);
+ ImageUtils::freeImage(gPreviewImage[LR]);
+ ImageUtils::freeImage(gPreviewImage[HR]);
+ sem_post(&gPreviewImage_semaphore);
- sem_destroy(&gPreviewImageRGB_semaphore);
- sem_destroy(&gPreviewImageReady_semaphore);
+ sem_destroy(&gPreviewImage_semaphore);
}
extern "C"
@@ -287,11 +352,17 @@ JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init(
{
gSurfTexRenderer[LR].InitializeGLProgram();
gSurfTexRenderer[HR].InitializeGLProgram();
- gWarper.InitializeGLProgram();
+ gYVURenderer[LR].InitializeGLProgram();
+ gYVURenderer[HR].InitializeGLProgram();
+ gWarper1.InitializeGLProgram();
+ gWarper2.InitializeGLProgram();
gPreview.InitializeGLProgram();
- gBuffer.InitializeGLContext();
+ gBuffer[0].InitializeGLContext();
+ gBuffer[1].InitializeGLContext();
gBufferInput[LR].InitializeGLContext();
gBufferInput[HR].InitializeGLContext();
+ gBufferInputYVU[LR].InitializeGLContext();
+ gBufferInputYVU[HR].InitializeGLContext();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -306,18 +377,25 @@ JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init(
JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset(
JNIEnv * env, jobject obj, jint width, jint height)
{
- gBuffer.Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA);
+ gBuffer[0].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA);
+ gBuffer[1].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA);
+
+ gBufferInput[LR].Init(gPreviewImageWidth[LR],
+ gPreviewImageHeight[LR], GL_RGBA);
+
+ gBufferInput[HR].Init(gPreviewImageWidth[HR],
+ gPreviewImageHeight[HR], GL_RGBA);
- gBufferInput[LR].Init(gPreviewImageRGBWidth[LR],
- gPreviewImageRGBHeight[LR], GL_RGBA);
+ gBufferInputYVU[LR].Init(gPreviewImageWidth[LR],
+ gPreviewImageHeight[LR], GL_RGBA);
- gBufferInput[HR].Init(gPreviewImageRGBWidth[HR],
- gPreviewImageRGBHeight[HR], GL_RGBA);
+ gBufferInputYVU[HR].Init(gPreviewImageWidth[HR],
+ gPreviewImageHeight[HR], GL_RGBA);
- sem_wait(&gPreviewImageRGB_semaphore);
- ClearPreviewImageRGB(LR);
- ClearPreviewImageRGB(HR);
- sem_post(&gPreviewImageRGB_semaphore);
+ sem_wait(&gPreviewImage_semaphore);
+ ClearPreviewImage(LR);
+ ClearPreviewImage(HR);
+ sem_post(&gPreviewImage_semaphore);
// bind the surface texture
bindSurfaceTexture(gSurfaceTextureID[0]);
@@ -336,20 +414,43 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset(
gSurfTexRenderer[HR].SetInputTextureName(gSurfaceTextureID[0]);
gSurfTexRenderer[HR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM);
- gWarper.SetupGraphics(&gBuffer);
- gWarper.Clear(0.0, 0.0, 0.0, 1.0);
- gWarper.SetViewportMatrix(gPreviewImageRGBWidth[LR],
- gPreviewImageRGBHeight[LR], gBuffer.GetWidth(),
- gBuffer.GetHeight());
- gWarper.SetScalingMatrix(1.0f, 1.0f);
- gWarper.SetInputTextureName(gBufferInput[LR].GetTextureName());
- gWarper.SetInputTextureType(GL_TEXTURE_2D);
+ gYVURenderer[LR].SetupGraphics(&gBufferInputYVU[LR]);
+ gYVURenderer[LR].Clear(0.0, 0.0, 0.0, 1.0);
+ gYVURenderer[LR].SetInputTextureName(gBufferInput[LR].GetTextureName());
+ gYVURenderer[LR].SetInputTextureType(GL_TEXTURE_2D);
+
+ gYVURenderer[HR].SetupGraphics(&gBufferInputYVU[HR]);
+ gYVURenderer[HR].Clear(0.0, 0.0, 0.0, 1.0);
+ gYVURenderer[HR].SetInputTextureName(gBufferInput[HR].GetTextureName());
+ gYVURenderer[HR].SetInputTextureType(GL_TEXTURE_2D);
+
+ // gBufferInput[LR] --> gWarper1 --> gBuffer[gCurrentFBOIndex]
+ gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
+ gWarper1.SetViewportMatrix(gPreviewImageWidth[LR],
+ gPreviewImageHeight[LR], gBuffer[gCurrentFBOIndex].GetWidth(),
+ gBuffer[gCurrentFBOIndex].GetHeight());
+ gWarper1.SetScalingMatrix(1.0f, 1.0f);
+ gWarper1.SetInputTextureName(gBufferInput[LR].GetTextureName());
+ gWarper1.SetInputTextureType(GL_TEXTURE_2D);
+
+ // gBuffer[gCurrentFBOIndex] --> gWarper2 --> gBuffer[1-gCurrentFBOIndex]
+ gWarper2.SetupGraphics(&gBuffer[1-gCurrentFBOIndex]);
+ gWarper2.Clear(0.0, 0.0, 0.0, 1.0);
+ gWarper2.SetViewportMatrix(1, 1, 1, 1);
+ gWarper2.SetScalingMatrix(1.0f, 1.0f);
+ gWarper2.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
+ gWarper2.SetInputTextureType(GL_TEXTURE_2D);
gPreview.SetupGraphics(width, height);
gPreview.Clear(0.0, 0.0, 0.0, 1.0);
gPreview.SetViewportMatrix(1, 1, 1, 1);
- gPreview.SetScalingMatrix(1.0f, -1.0f);
- gPreview.SetInputTextureName(gBuffer.GetTextureName());
+ // Scale the previewFBO so that the viewfinder window fills the layout height
+ // while maintaining the image aspect ratio
+ gPreview.SetScalingMatrix((PREVIEW_FBO_WIDTH_SCALE / PREVIEW_FBO_HEIGHT_SCALE) *
+ (gPreviewImageWidth[LR] / gPreviewImageHeight[LR]) / (width / height) *
+ PREVIEW_FBO_HEIGHT_SCALE, -1.0f*PREVIEW_FBO_HEIGHT_SCALE);
+ gPreview.SetInputTextureName(gBuffer[1-gCurrentFBOIndex].GetTextureName());
gPreview.SetInputTextureType(GL_TEXTURE_2D);
}
@@ -367,47 +468,108 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preproces
gSurfTexRenderer[HR].DrawTexture(g_dAffinetransIdent);
}
+#ifndef now_ms
+#include <time.h>
+static double
+now_ms(void)
+{
+ //struct timespec res;
+ struct timeval res;
+ //clock_gettime(CLOCK_REALTIME, &res);
+ gettimeofday(&res, NULL);
+ return 1000.0*res.tv_sec + (double)res.tv_usec/1e3;
+}
+#endif
+
+
+
JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU(
JNIEnv * env, jobject obj)
{
- sem_wait(&gPreviewImageRGB_semaphore);
+ double t0, t1, time_c;
+
+ t0 = now_ms();
+
+ gYVURenderer[LR].DrawTexture();
+ gYVURenderer[HR].DrawTexture();
+
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGV("YVU Rendering: %g ms", time_c);
+
+ sem_wait(&gPreviewImage_semaphore);
// Bind to the input LR FBO and read the Low-Res data from there...
- glBindFramebuffer(GL_FRAMEBUFFER, gBufferInput[LR].GetFrameBufferName());
+ glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[LR].GetFrameBufferName());
+ t0 = now_ms();
glReadPixels(0,
0,
gBufferInput[LR].GetWidth(),
gBufferInput[LR].GetHeight(),
GL_RGBA,
GL_UNSIGNED_BYTE,
- gPreviewImageRGB[LR]);
+ gPreviewImage[LR]);
checkGlError("glReadPixels LR");
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGV("glReadPixels LR: %g ms", time_c);
// Bind to the input HR FBO and read the high-res data from there...
- glBindFramebuffer(GL_FRAMEBUFFER, gBufferInput[HR].GetFrameBufferName());
+ glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[HR].GetFrameBufferName());
+ t0 = now_ms();
glReadPixels(0,
0,
gBufferInput[HR].GetWidth(),
gBufferInput[HR].GetHeight(),
GL_RGBA,
GL_UNSIGNED_BYTE,
- gPreviewImageRGB[HR]);
+ gPreviewImage[HR]);
checkGlError("glReadPixels HR");
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGV("glReadPixels HR: %g ms", time_c);
- sem_post(&gPreviewImageRGB_semaphore);
+ sem_post(&gPreviewImage_semaphore);
}
JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step(
JNIEnv * env, jobject obj)
{
- // Use the gWarper shader to apply the current frame transformation to the
- // current frame and then add it to the gBuffer FBO.
- gWarper.DrawTexture(g_dAffinetransGL);
+ if(!gWarpImage)
+ {
+ gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
+ gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
+
+ // Use gWarper1 shader to apply the current frame transformation to the
+ // current frame and then add it to the gBuffer FBO.
+ gWarper1.DrawTexture(g_dAffinetransGL);
+
+ // Use the gPreview shader to apply the inverse of the current frame
+ // transformation to the gBuffer FBO and render it to the screen.
+ gPreview.DrawTexture(g_dAffinetransInvGL);
+ }
+ else
+ {
+ gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
+ gWarper2.SetupGraphics(&gBuffer[1-gCurrentFBOIndex]);
+ gWarper2.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
+ gPreview.SetInputTextureName(gBuffer[1-gCurrentFBOIndex].GetTextureName());
- // Use the gPreview shader to apply the inverse of the current frame
- // transformation to the gBuffer FBO and render it to the screen.
- gPreview.DrawTexture(g_dAffinetransInvGL);
+ // Use gWarper1 shader to apply the current frame transformation to the
+ // current frame and then add it to the gBuffer FBO.
+ gWarper1.DrawTexture(g_dAffinetransGL);
+
+ // Use gWarper2 to translate the contents of the gBuffer FBO and copy
+ // it into the second gBuffer FBO
+ gWarper2.DrawTexture(g_dTranslationGL);
+
+ // Use the gPreview shader to apply the inverse of the current frame
+ // transformation to the gBuffer FBO and render it to the screen.
+ gPreview.DrawTexture(g_dAffinetransInvGL);
+
+ gCurrentFBOIndex = 1 - gCurrentFBOIndex;
+ }
}
JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping(
@@ -416,7 +578,8 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarpin
// TODO: Review this logic
if(gWarpImage != (bool) flag) //switching from viewfinder to capture or vice-versa
{
- gWarper.Clear(0.0, 0.0, 0.0, 1.0);
+ gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
+ gWarper2.Clear(0.0, 0.0, 0.0, 1.0);
gPreview.Clear(0.0, 0.0, 0.0, 1.0);
// Clear the screen to black.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -432,21 +595,18 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready(
{
if(!gWarpImage)
{
- // TODO: Review this logic...
- UpdateWarpTransformation(g_dAffinetransIdent);
+ UpdateWarpTransformation(g_dIdent3x3);
for(int i=0; i<16; i++)
{
- g_dAffinetrans[i] = g_dAffinetransIdent[i];
g_dAffinetransInv[i] = g_dAffinetransIdent[i];
}
- g_dAffinetrans[12] = 1.0f;
- g_dAffinetrans[13] = 1.0f;
}
for(int i=0; i<16; i++)
{
g_dAffinetransGL[i] = g_dAffinetrans[i];
g_dAffinetransInvGL[i] = g_dAffinetransInv[i];
+ g_dTranslationGL[i] = g_dTranslation[i];
}
}