Merge "Video editor API update - rework for Patch Set 3" into honeycomb
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 002e48b..79c33f5 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -40,6 +40,10 @@
enum { MIN_BUFFER_SLOTS = 3 };
enum { NUM_BUFFER_SLOTS = 32 };
+ struct FrameAvailableListener : public virtual RefBase {
+ virtual void onFrameAvailable() = 0;
+ };
+
// tex indicates the name OpenGL texture to which images are to be streamed.
// This texture name cannot be changed once the SurfaceTexture is created.
SurfaceTexture(GLuint tex);
@@ -93,6 +97,10 @@
// functions.
void getTransformMatrix(float mtx[16]);
+ // setFrameAvailableListener sets the listener object that will be notified
+ // when a new frame becomes available.
+ void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+
private:
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
@@ -195,6 +203,11 @@
// to a buffer, but other processes do.
Vector<sp<GraphicBuffer> > mAllocdBuffers;
+ // mFrameAvailableListener is the listener object that will be called when a
+ // new frame becomes available. If it is not NULL it will be called from
+ // queueBuffer.
+ sp<FrameAvailableListener> mFrameAvailableListener;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 5532052..d783caf 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -100,6 +100,9 @@
friend class MediaPlayer;
// for testing
friend class Test;
+ // videoEditor preview classes
+ friend class VideoEditorPreviewController;
+
const sp<ISurface>& getISurface() const { return mSurface; }
@@ -181,6 +184,9 @@
friend class SoftwareRenderer;
// this is just to be able to write some unit tests
friend class Test;
+ // videoEditor preview classes
+ friend class VideoEditorPreviewController;
+ friend class PreviewRenderer;
private:
friend class SurfaceComposerClient;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 447de76..1dadd53 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -166,6 +166,9 @@
mLastQueued = buf;
mLastQueuedCrop = mNextCrop;
mLastQueuedTransform = mNextTransform;
+ if (mFrameAvailableListener != 0) {
+ mFrameAvailableListener->onFrameAvailable();
+ }
return OK;
}
@@ -237,43 +240,68 @@
LOGV("SurfaceTexture::updateTexImage");
Mutex::Autolock lock(mMutex);
- float* xform = mtxIdentity;
- switch (mCurrentTransform) {
- case 0:
- xform = mtxIdentity;
- break;
- case NATIVE_WINDOW_TRANSFORM_FLIP_H:
- xform = mtxFlipH;
- break;
- case NATIVE_WINDOW_TRANSFORM_FLIP_V:
- xform = mtxFlipV;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_90:
- xform = mtxRot90;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_180:
- xform = mtxRot180;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_270:
- xform = mtxRot270;
- break;
- default:
- LOGE("getTransformMatrix: unknown transform: %d", mCurrentTransform);
+ float xform[16];
+ for (int i = 0; i < 16; i++) {
+ xform[i] = mtxIdentity[i];
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ float result[16];
+ mtxMul(result, xform, mtxFlipH);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ float result[16];
+ mtxMul(result, xform, mtxFlipV);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ float result[16];
+ mtxMul(result, xform, mtxRot90);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
}
sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
- float tx = float(mCurrentCrop.left) / float(buf->getWidth());
- float ty = float(mCurrentCrop.bottom) / float(buf->getHeight());
- float sx = float(mCurrentCrop.width()) / float(buf->getWidth());
- float sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+ float tx, ty, sx, sy;
+ if (!mCurrentCrop.isEmpty()) {
+ tx = float(mCurrentCrop.left) / float(buf->getWidth());
+ ty = float(buf->getHeight() - mCurrentCrop.bottom) /
+ float(buf->getHeight());
+ sx = float(mCurrentCrop.width()) / float(buf->getWidth());
+ sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+ } else {
+ tx = 0.0f;
+ ty = 0.0f;
+ sx = 1.0f;
+ sy = 1.0f;
+ }
float crop[16] = {
- sx, 0, 0, sx*tx,
- 0, sy, 0, sy*ty,
+ sx, 0, 0, 0,
+ 0, sy, 0, 0,
0, 0, 1, 0,
- 0, 0, 0, 1,
+ sx*tx, sy*ty, 0, 1,
};
- mtxMul(mtx, crop, xform);
+ float mtxBeforeFlipV[16];
+ mtxMul(mtxBeforeFlipV, crop, xform);
+
+ // SurfaceFlinger expects the top of its window textures to be at a Y
+ // coordinate of 0, so SurfaceTexture must behave the same way. We don't
+ // want to expose this to applications, however, so we must add an
+ // additional vertical flip to the transform after all the other transforms.
+ mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
+}
+
+void SurfaceTexture::setFrameAvailableListener(
+ const sp<FrameAvailableListener>& l) {
+ LOGV("SurfaceTexture::setFrameAvailableListener");
+ Mutex::Autolock lock(mMutex);
+ mFrameAvailableListener = l;
}
void SurfaceTexture::freeAllBuffers() {
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 386cc5d..ed36171 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,6 +62,8 @@
"EGL_KHR_image_base "
"EGL_KHR_image_pixmap "
"EGL_KHR_gl_texture_2D_image "
+ "EGL_KHR_gl_texture_cubemap_image "
+ "EGL_KHR_gl_renderbuffer_image "
"EGL_KHR_fence_sync "
"EGL_ANDROID_image_native_buffer "
"EGL_ANDROID_swap_rectangle "
@@ -1471,6 +1473,29 @@
return result;
}
+// Note: Similar implementations of these functions also exist in
+// gl2.cpp and gl.cpp, and are used by applications that call the
+// exported entry points directly.
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
+static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
+
+static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
+{
+ GLeglImageOES implImage =
+ (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+ glEGLImageTargetTexture2DOES_impl(target, implImage);
+}
+
+static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
+{
+ GLeglImageOES implImage =
+ (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+ glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
+}
+
__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
{
// eglGetProcAddress() could be the very first function called
@@ -1531,6 +1556,16 @@
}
if (found) {
addr = gExtensionForwarders[slot];
+
+ if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
+ glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
+ addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
+ }
+ if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
+ glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
+ addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
+ }
+
gGLExtentionMap.add(name, addr);
gGLExtentionSlot++;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 154b822..65ad956 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2132,6 +2132,9 @@
sh = (!sh) ? hw_h : sh;
const size_t size = sw * sh * 4;
+ LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
+ sw, sh, minLayerZ, maxLayerZ);
+
// make sure to clear all GL error flags
while ( glGetError() != GL_NO_ERROR ) ;
@@ -2146,6 +2149,9 @@
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+
+ LOGD("screenshot: FBO created, status=0x%x", status);
+
if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
// invert everything, b/c glReadPixel() below will invert the FB
@@ -2161,6 +2167,8 @@
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
+ LOGD("screenshot: glClear() issued");
+
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
@@ -2171,6 +2179,8 @@
}
}
+ LOGD("screenshot: All layers rendered");
+
// XXX: this is needed on tegra
glScissor(0, 0, sw, sh);
@@ -2185,6 +2195,10 @@
new MemoryHeapBase(size, 0, "screen-capture") );
void* const ptr = base->getBase();
if (ptr) {
+
+ LOGD("screenshot: about to call glReadPixels(0,0,%d,%d,...,%p)",
+ sw, sh, ptr);
+
// capture the screen with glReadPixels()
glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
if (glGetError() == GL_NO_ERROR) {
@@ -2197,25 +2211,32 @@
} else {
result = NO_MEMORY;
}
+
+ LOGD("screenshot: glReadPixels() returned %s", strerror(result));
+
}
glEnable(GL_SCISSOR_TEST);
glViewport(0, 0, hw_w, hw_h);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
-
-
} else {
result = BAD_VALUE;
}
+ LOGD("screenshot: about to release FBO resources");
+
// release FBO resources
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
+ LOGD("screenshot: about to call compositionComplete()");
+
hw.compositionComplete();
+ LOGD("screenshot: result = %s", strerror(result));
+
return result;
}