vnc: Use CpuConsumer

There's no need to use a GLConsumer unless we really want to draw
on the surface or send it to a hardware encoder. Get rid of all
this stuff and just use CpuConsumer.
diff --git a/Android.mk b/Android.mk
index e101f3b..2f0f786 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,9 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-    src/EglWindow.cpp \
     src/InputDevice.cpp \
-    src/Program.cpp \
     src/VirtualDisplay.cpp \
     src/VNCFlinger.cpp \
     src/main.cpp
@@ -25,14 +23,12 @@
     libssl \
     libui \
     libutils \
-    libz \
-    libEGL \
-    libGLESv3
+    libz
 
 LOCAL_STATIC_LIBRARIES += \
     libvncserver
 
-LOCAL_CFLAGS := -Ofast -Werror 
+LOCAL_CFLAGS := -Ofast -Werror -std=c++11
 LOCAL_CFLAGS += -DLOG_NDEBUG=0
 
 #LOCAL_CXX := /usr/bin/include-what-you-use
diff --git a/src/EglWindow.cpp b/src/EglWindow.cpp
deleted file mode 100644
index 60e9b49..0000000
--- a/src/EglWindow.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "VNC-EglWindow"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
-#include <gui/Surface.h>
-
-#include "EglWindow.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <assert.h>
-
-using namespace android;
-
-
-status_t EglWindow::createWindow(const sp<IGraphicBufferProducer>& surface) {
-    if (mEglSurface != EGL_NO_SURFACE) {
-        ALOGE("surface already created");
-        return UNKNOWN_ERROR;
-    }
-    status_t err = eglSetupContext(false);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    // Cache the current dimensions.  We're not expecting these to change.
-    surface->query(NATIVE_WINDOW_WIDTH, &mWidth);
-    surface->query(NATIVE_WINDOW_HEIGHT, &mHeight);
-
-    // Output side (EGL surface to draw on).
-    sp<ANativeWindow> anw = new Surface(surface);
-    mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, anw.get(),
-            NULL);
-    if (mEglSurface == EGL_NO_SURFACE) {
-        ALOGE("eglCreateWindowSurface error: %#x", eglGetError());
-        eglRelease();
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-status_t EglWindow::createPbuffer(int width, int height) {
-    if (mEglSurface != EGL_NO_SURFACE) {
-        ALOGE("surface already created");
-        return UNKNOWN_ERROR;
-    }
-    status_t err = eglSetupContext(true);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    mWidth = width;
-    mHeight = height;
-
-    EGLint pbufferAttribs[] = {
-            EGL_WIDTH, width,
-            EGL_HEIGHT, height,
-            EGL_NONE
-    };
-    mEglSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, pbufferAttribs);
-    if (mEglSurface == EGL_NO_SURFACE) {
-        ALOGE("eglCreatePbufferSurface error: %#x", eglGetError());
-        eglRelease();
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-status_t EglWindow::makeCurrent() const {
-    if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-        ALOGE("eglMakeCurrent failed: %#x", eglGetError());
-        return UNKNOWN_ERROR;
-    }
-    return NO_ERROR;
-}
-
-status_t EglWindow::eglSetupContext(bool forPbuffer) {
-    EGLBoolean result;
-
-    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (mEglDisplay == EGL_NO_DISPLAY) {
-        ALOGE("eglGetDisplay failed: %#x", eglGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    EGLint majorVersion, minorVersion;
-    result = eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
-    if (result != EGL_TRUE) {
-        ALOGE("eglInitialize failed: %#x", eglGetError());
-        return UNKNOWN_ERROR;
-    }
-    ALOGV("Initialized EGL v%d.%d", majorVersion, minorVersion);
-
-    EGLint numConfigs = 0;
-    EGLint windowConfigAttribs[] = {
-            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-            EGL_RECORDABLE_ANDROID, 1,
-            EGL_RED_SIZE, 8,
-            EGL_GREEN_SIZE, 8,
-            EGL_BLUE_SIZE, 8,
-            EGL_ALPHA_SIZE, 8,
-    };
-    EGLint pbufferConfigAttribs[] = {
-            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
-            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-            EGL_RED_SIZE, 8,
-            EGL_GREEN_SIZE, 8,
-            EGL_BLUE_SIZE, 8,
-            EGL_ALPHA_SIZE, 8,
-            EGL_NONE
-    };
-    result = eglChooseConfig(mEglDisplay,
-            forPbuffer ? pbufferConfigAttribs : windowConfigAttribs,
-            &mEglConfig, 1, &numConfigs);
-    if (result != EGL_TRUE) {
-        ALOGE("eglChooseConfig error: %#x", eglGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    EGLint contextAttribs[] = {
-        EGL_CONTEXT_CLIENT_VERSION, 3,
-        EGL_NONE
-    };
-    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
-            contextAttribs);
-    if (mEglContext == EGL_NO_CONTEXT) {
-        ALOGE("eglCreateContext error: %#x", eglGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-void EglWindow::eglRelease() {
-    ALOGV("EglWindow::eglRelease");
-    if (mEglDisplay != EGL_NO_DISPLAY) {
-        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                EGL_NO_CONTEXT);
-
-        if (mEglContext != EGL_NO_CONTEXT) {
-            eglDestroyContext(mEglDisplay, mEglContext);
-        }
-
-        if (mEglSurface != EGL_NO_SURFACE) {
-            eglDestroySurface(mEglDisplay, mEglSurface);
-        }
-    }
-
-    mEglDisplay = EGL_NO_DISPLAY;
-    mEglContext = EGL_NO_CONTEXT;
-    mEglSurface = EGL_NO_SURFACE;
-    mEglConfig = NULL;
-
-    eglReleaseThread();
-}
-
-// Sets the presentation time on the current EGL buffer.
-void EglWindow::presentationTime(nsecs_t whenNsec) const {
-    eglPresentationTimeANDROID(mEglDisplay, mEglSurface, whenNsec);
-}
-
-// Swaps the EGL buffer.
-void EglWindow::swapBuffers() const {
-    eglSwapBuffers(mEglDisplay, mEglSurface);
-}
diff --git a/src/EglWindow.h b/src/EglWindow.h
deleted file mode 100644
index 69d0c31..0000000
--- a/src/EglWindow.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCREENRECORD_EGL_WINDOW_H
-#define SCREENRECORD_EGL_WINDOW_H
-
-#include <gui/BufferQueue.h>
-#include <utils/Errors.h>
-
-#include <EGL/egl.h>
-
-namespace android {
-
-/*
- * Wraps EGL display, context, surface, config for a window surface.
- *
- * Not thread safe.
- */
-class EglWindow {
-public:
-    EglWindow() :
-        mEglDisplay(EGL_NO_DISPLAY),
-        mEglContext(EGL_NO_CONTEXT),
-        mEglSurface(EGL_NO_SURFACE),
-        mEglConfig(NULL),
-        mWidth(0),
-        mHeight(0)
-        {}
-    ~EglWindow() { eglRelease(); }
-
-    // Creates an EGL window for the supplied surface.
-    status_t createWindow(const sp<IGraphicBufferProducer>& surface);
-
-    // Creates an EGL pbuffer surface.
-    status_t createPbuffer(int width, int height);
-
-    // Return width and height values (obtained from IGBP).
-    int getWidth() const { return mWidth; }
-    int getHeight() const { return mHeight; }
-
-    // Release anything we created.
-    void release() { eglRelease(); }
-
-    // Make this context current.
-    status_t makeCurrent() const;
-
-    // Sets the presentation time on the current EGL buffer.
-    void presentationTime(nsecs_t whenNsec) const;
-
-    // Swaps the EGL buffer.
-    void swapBuffers() const;
-
-private:
-    EglWindow(const EglWindow&);
-    EglWindow& operator=(const EglWindow&);
-
-    // Init display, create config and context.
-    status_t eglSetupContext(bool forPbuffer);
-    void eglRelease();
-
-    // Basic EGL goodies.
-    EGLDisplay mEglDisplay;
-    EGLContext mEglContext;
-    EGLSurface mEglSurface;
-    EGLConfig mEglConfig;
-
-    // Surface dimensions.
-    int mWidth;
-    int mHeight;
-};
-
-}; // namespace android
-
-#endif /*SCREENRECORD_EGL_WINDOW_H*/
diff --git a/src/Program.cpp b/src/Program.cpp
deleted file mode 100644
index e2dbd76..0000000
--- a/src/Program.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "VNC"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "Program.h"
-
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-#include <GLES2/gl2ext.h>
-
-#include <assert.h>
-
-using namespace android;
-
-// 4x4 identity matrix
-const float Program::kIdentity[] = {
-        1.0f, 0.0f, 0.0f, 0.0f,
-        0.0f, 1.0f, 0.0f, 0.0f,
-        0.0f, 0.0f, 1.0f, 0.0f,
-        0.0f, 0.0f, 0.0f, 1.0f
-};
-
-// Simple vertex shader.  Texture coord calc includes matrix for GLConsumer
-// transform.
-static const char* kVertexShader =
-        "uniform mat4 uMVPMatrix;\n"
-        "uniform mat4 uGLCMatrix;\n"
-        "attribute vec4 aPosition;\n"
-        "attribute vec4 aTextureCoord;\n"
-        "varying vec2 vTextureCoord;\n"
-        "void main() {\n"
-        "    gl_Position = uMVPMatrix * aPosition;\n"
-        "    vTextureCoord = (uGLCMatrix * aTextureCoord).xy;\n"
-        "}\n";
-
-// Trivial fragment shader for external texture.
-static const char* kExtFragmentShader =
-        "#extension GL_OES_EGL_image_external : require\n"
-        "precision mediump float;\n"
-        "varying vec2 vTextureCoord;\n"
-        "uniform samplerExternalOES uTexture;\n"
-        "void main() {\n"
-        "    gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
-        "}\n";
-
-// Trivial fragment shader for mundane texture.
-static const char* kFragmentShader =
-        "precision mediump float;\n"
-        "varying vec2 vTextureCoord;\n"
-        "uniform sampler2D uTexture;\n"
-        "void main() {\n"
-        "    gl_FragColor = texture2D(uTexture, vTextureCoord);\n"
-        //"    gl_FragColor = vec4(0.2, 1.0, 0.2, 1.0);\n"
-        "}\n";
-
-status_t Program::setup(ProgramType type) {
-    ALOGV("Program::setup type=%d", type);
-    status_t err;
-
-    mProgramType = type;
-
-    GLuint program;
-    if (type == PROGRAM_TEXTURE_2D) {
-        err = createProgram(&program, kVertexShader, kFragmentShader);
-    } else {
-        err = createProgram(&program, kVertexShader, kExtFragmentShader);
-    }
-    if (err != NO_ERROR) {
-        return err;
-    }
-    assert(program != 0);
-
-    maPositionLoc = glGetAttribLocation(program, "aPosition");
-    maTextureCoordLoc = glGetAttribLocation(program, "aTextureCoord");
-    muMVPMatrixLoc = glGetUniformLocation(program, "uMVPMatrix");
-    muGLCMatrixLoc = glGetUniformLocation(program, "uGLCMatrix");
-    muTextureLoc = glGetUniformLocation(program, "uTexture");
-    if ((maPositionLoc | maTextureCoordLoc | muMVPMatrixLoc |
-            muGLCMatrixLoc | muTextureLoc) == -1) {
-        ALOGE("Attrib/uniform lookup failed: %#x", glGetError());
-        glDeleteProgram(program);
-        return UNKNOWN_ERROR;
-    }
-
-    mProgram = program;
-    return NO_ERROR;
-}
-
-void Program::release() {
-    ALOGV("Program::release");
-    if (mProgram != 0) {
-        glDeleteProgram(mProgram);
-        mProgram = 0;
-    }
-}
-
-status_t Program::createProgram(GLuint* outPgm, const char* vertexShader,
-        const char* fragmentShader) {
-    GLuint vs, fs;
-    status_t err;
-
-    err = compileShader(GL_VERTEX_SHADER, vertexShader, &vs);
-    if (err != NO_ERROR) {
-        return err;
-    }
-    err = compileShader(GL_FRAGMENT_SHADER, fragmentShader, &fs);
-    if (err != NO_ERROR) {
-        glDeleteShader(vs);
-        return err;
-    }
-
-    GLuint program;
-    err = linkShaderProgram(vs, fs, &program);
-    glDeleteShader(vs);
-    glDeleteShader(fs);
-    if (err == NO_ERROR) {
-        *outPgm = program;
-    }
-    return err;
-}
-
-status_t Program::compileShader(GLenum shaderType, const char* src,
-        GLuint* outShader) {
-    GLuint shader = glCreateShader(shaderType);
-    if (shader == 0) {
-        ALOGE("glCreateShader error: %#x", glGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    glShaderSource(shader, 1, &src, NULL);
-    glCompileShader(shader);
-
-    GLint compiled = 0;
-    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
-    if (!compiled) {
-        ALOGE("Compile of shader type %d failed", shaderType);
-        GLint infoLen = 0;
-        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-        if (infoLen) {
-            char* buf = new char[infoLen];
-            if (buf) {
-                glGetShaderInfoLog(shader, infoLen, NULL, buf);
-                ALOGE("Compile log: %s", buf);
-                delete[] buf;
-            }
-        }
-        glDeleteShader(shader);
-        return UNKNOWN_ERROR;
-    }
-    *outShader = shader;
-    return NO_ERROR;
-}
-
-status_t Program::linkShaderProgram(GLuint vs, GLuint fs, GLuint* outPgm) {
-    GLuint program = glCreateProgram();
-    if (program == 0) {
-        ALOGE("glCreateProgram error: %#x", glGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    glAttachShader(program, vs);
-    glAttachShader(program, fs);
-    glLinkProgram(program);
-    GLint linkStatus = GL_FALSE;
-    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-    if (linkStatus != GL_TRUE) {
-        ALOGE("glLinkProgram failed");
-        GLint bufLength = 0;
-        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
-        if (bufLength) {
-            char* buf = new char[bufLength];
-            if (buf) {
-                glGetProgramInfoLog(program, bufLength, NULL, buf);
-                ALOGE("Link log: %s", buf);
-                delete[] buf;
-            }
-        }
-        glDeleteProgram(program);
-        return UNKNOWN_ERROR;
-    }
-
-    *outPgm = program;
-    return NO_ERROR;
-}
-
-
-
-status_t Program::blit(GLuint texName, const float* texMatrix,
-        int32_t x, int32_t y, int32_t w, int32_t h, bool invert) const {
-    ALOGV("Program::blit %d xy=%d,%d wh=%d,%d", texName, x, y, w, h);
-
-    const float pos[] = {
-        float(x),   float(y+h),
-        float(x+w), float(y+h),
-        float(x),   float(y),
-        float(x+w), float(y),
-    };
-    const float uv[] = {
-        0.0f, 0.0f,
-        1.0f, 0.0f,
-        0.0f, 1.0f,
-        1.0f, 1.0f,
-    };
-    status_t err;
-
-    err = beforeDraw(texName, texMatrix, pos, uv, invert);
-    if (err == NO_ERROR) {
-        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-        err = afterDraw();
-    }
-    return err;
-}
-
-status_t Program::drawTriangles(GLuint texName, const float* texMatrix,
-        const float* vertices, const float* texes, size_t count) const {
-    ALOGV("Program::drawTriangles texName=%d", texName);
-
-    status_t err;
-
-    err = beforeDraw(texName, texMatrix, vertices, texes, false);
-    if (err == NO_ERROR) {
-        glDrawArrays(GL_TRIANGLES, 0, count);
-        err = afterDraw();
-    }
-    return err;
-}
-
-status_t Program::beforeDraw(GLuint texName, const float* texMatrix,
-        const float* vertices, const float* texes, bool invert) const {
-    // Create an orthographic projection matrix based on viewport size.
-    GLint vp[4];
-    glGetIntegerv(GL_VIEWPORT, vp);
-    float screenToNdc[16] = {
-        2.0f/float(vp[2]),  0.0f,               0.0f,   0.0f,
-        0.0f,               -2.0f/float(vp[3]), 0.0f,   0.0f,
-        0.0f,               0.0f,               1.0f,   0.0f,
-        -1.0f,              1.0f,               0.0f,   1.0f,
-    };
-    if (invert) {
-        screenToNdc[5] = -screenToNdc[5];
-        screenToNdc[13] = -screenToNdc[13];
-    }
-
-    glUseProgram(mProgram);
-
-    glVertexAttribPointer(maPositionLoc, 2, GL_FLOAT, GL_FALSE, 0, vertices);
-    glVertexAttribPointer(maTextureCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, texes);
-    glEnableVertexAttribArray(maPositionLoc);
-    glEnableVertexAttribArray(maTextureCoordLoc);
-
-    glUniformMatrix4fv(muMVPMatrixLoc, 1, GL_FALSE, screenToNdc);
-    glUniformMatrix4fv(muGLCMatrixLoc, 1, GL_FALSE, texMatrix);
-
-    glActiveTexture(GL_TEXTURE0);
-
-    switch (mProgramType) {
-    case PROGRAM_EXTERNAL_TEXTURE:
-        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName);
-        break;
-    case PROGRAM_TEXTURE_2D:
-        glBindTexture(GL_TEXTURE_2D, texName);
-        break;
-    default:
-        ALOGE("unexpected program type %d", mProgramType);
-        return UNKNOWN_ERROR;
-    }
-
-    glUniform1i(muTextureLoc, 0);
-
-    GLenum glErr;
-    if ((glErr = glGetError()) != GL_NO_ERROR) {
-        ALOGE("GL error before draw: %#x", glErr);
-        glDisableVertexAttribArray(maPositionLoc);
-        glDisableVertexAttribArray(maTextureCoordLoc);
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
-
-status_t Program::afterDraw() const {
-    glDisableVertexAttribArray(maPositionLoc);
-    glDisableVertexAttribArray(maTextureCoordLoc);
-
-    GLenum glErr;
-    if ((glErr = glGetError()) != GL_NO_ERROR) {
-        ALOGE("GL error after draw: %#x", glErr);
-        return UNKNOWN_ERROR;
-    }
-
-    return NO_ERROR;
-}
diff --git a/src/Program.h b/src/Program.h
deleted file mode 100644
index 1d70887..0000000
--- a/src/Program.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCREENRECORD_PROGRAM_H
-#define SCREENRECORD_PROGRAM_H
-
-#include <utils/Errors.h>
-
-#include <EGL/egl.h>
-#include <GLES3/gl3.h>
-
-namespace android {
-
-/*
- * Utility class for GLES rendering.
- *
- * Not thread-safe.
- */
-class Program {
-public:
-    enum ProgramType { PROGRAM_UNKNOWN=0, PROGRAM_EXTERNAL_TEXTURE,
-            PROGRAM_TEXTURE_2D };
-
-    Program() :
-        mProgramType(PROGRAM_UNKNOWN),
-        mProgram(0),
-        maPositionLoc(0),
-        maTextureCoordLoc(0),
-        muMVPMatrixLoc(0),
-        muGLCMatrixLoc(0),
-        muTextureLoc(0)
-        {}
-    ~Program() { release(); }
-
-    // Initialize the program for use with the specified texture type.
-    status_t setup(ProgramType type);
-
-    // Release the program and associated resources.
-    void release();
-
-    // Blit the specified texture to { x, y, x+w, y+h }.  Inverts the
-    // content if "invert" is set.
-    status_t blit(GLuint texName, const float* texMatrix,
-            int32_t x, int32_t y, int32_t w, int32_t h,
-            bool invert = false) const;
-
-    // Draw a number of triangles.
-    status_t drawTriangles(GLuint texName, const float* texMatrix,
-            const float* vertices, const float* texes, size_t count) const;
-
-    static const float kIdentity[];
-
-private:
-    Program(const Program&);
-    Program& operator=(const Program&);
-
-    // Common code for draw functions.
-    status_t beforeDraw(GLuint texName, const float* texMatrix,
-            const float* vertices, const float* texes, bool invert) const;
-    status_t afterDraw() const;
-
-    // GLES 2 shader utilities.
-    status_t createProgram(GLuint* outPgm, const char* vertexShader,
-            const char* fragmentShader);
-    static status_t compileShader(GLenum shaderType, const char* src,
-            GLuint* outShader);
-    static status_t linkShaderProgram(GLuint vs, GLuint fs, GLuint* outPgm);
-
-    ProgramType mProgramType;
-    GLuint mProgram;
-
-    GLint maPositionLoc;
-    GLint maTextureCoordLoc;
-    GLint muMVPMatrixLoc;
-    GLint muGLCMatrixLoc;
-    GLint muTextureLoc;
-};
-
-}; // namespace android
-
-#endif /*SCREENRECORD_PROGRAM_H*/
diff --git a/src/VNCFlinger.cpp b/src/VNCFlinger.cpp
index 70f741a..efd6cbc 100644
--- a/src/VNCFlinger.cpp
+++ b/src/VNCFlinger.cpp
@@ -14,6 +14,8 @@
 
 using namespace android;
 
+Mutex VNCFlinger::sUpdateMutex;
+
 status_t VNCFlinger::start() {
     Mutex::Autolock _l(mMutex);
 
@@ -74,19 +76,20 @@
     mVNCScreen->newClientHook = (rfbNewClientHookPtr) VNCFlinger::onNewClient;
     mVNCScreen->kbdAddEvent = InputDevice::keyEvent;
     mVNCScreen->ptrAddEvent = InputDevice::pointerEvent;
+    mVNCScreen->displayHook = (rfbDisplayHookPtr) VNCFlinger::onFrameStart;
+    mVNCScreen->displayFinishedHook = (rfbDisplayFinishedHookPtr) VNCFlinger::onFrameDone;
     mVNCScreen->serverFormat.trueColour = true;
     mVNCScreen->serverFormat.bitsPerPixel = 32;
     mVNCScreen->handleEventsEagerly = true;
-    mVNCScreen->deferUpdateTime = 16;
+    mVNCScreen->deferUpdateTime = 0;
     mVNCScreen->screenData = this;
-
     rfbInitServer(mVNCScreen);
 
     /* Mark as dirty since we haven't sent any updates at all yet. */
     rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
 
 
-    mVirtualDisplay = new VirtualDisplay(mVNCScreen);
+    mVirtualDisplay = new VirtualDisplay(mVNCScreen, &sUpdateMutex);
 
     return err;
 }
@@ -147,6 +150,23 @@
     return RFB_CLIENT_ACCEPT;
 }
 
+void VNCFlinger::onFrameStart(rfbClientPtr /* cl */) {
+    sUpdateMutex.lock();
+    ALOGV("frame start");
+}
+
+void VNCFlinger::onFrameDone(rfbClientPtr /* cl */, int status) {
+    sUpdateMutex.unlock();
+    ALOGV("frame done! %d", status);
+}
+
+void VNCFlinger::markFrame(void* frame, size_t stride) {
+    Mutex::Autolock _l(sUpdateMutex);
+    mVNCScreen->frameBuffer = (char *)frame;
+    mVNCScreen->paddedWidthInBytes = stride * 4;
+    rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
+}
+
 void VNCFlinger::rfbLogger(const char *format, ...) {
     va_list args;
     char buf[256];
diff --git a/src/VNCFlinger.h b/src/VNCFlinger.h
index c1e38ba..8c026b9 100644
--- a/src/VNCFlinger.h
+++ b/src/VNCFlinger.h
@@ -27,6 +27,8 @@
     virtual size_t addClient();
     virtual size_t removeClient();
 
+    virtual void markFrame(void* frame, size_t stride);
+
 private:
 
     virtual status_t setup_l();
@@ -34,6 +36,8 @@
 
     static ClientGoneHookPtr onClientGone(rfbClientPtr cl);
     static enum rfbNewClientAction onNewClient(rfbClientPtr cl);
+    static void onFrameStart(rfbClientPtr cl);
+    static void onFrameDone(rfbClientPtr cl, int result);
     static void rfbLogger(const char *format, ...);
 
     Condition mCondition;
@@ -48,6 +52,7 @@
     DisplayInfo mMainDpyInfo;
     
     Mutex mMutex;
+    static Mutex sUpdateMutex;
 
     sp<VirtualDisplay> mVirtualDisplay;
 
diff --git a/src/VirtualDisplay.cpp b/src/VirtualDisplay.cpp
index b44c64c..27cc00e 100644
--- a/src/VirtualDisplay.cpp
+++ b/src/VirtualDisplay.cpp
@@ -106,10 +106,10 @@
     Rect displayRect(offX, offY, offX + outWidth, offY + outHeight);
 
     if (mRotate) {
-        printf("Rotated content area is %ux%u at offset x=%d y=%d\n",
+        ALOGV("Rotated content area is %ux%u at offset x=%d y=%d\n",
                 outHeight, outWidth, offY, offX);
     } else {
-        printf("Content area is %ux%u at offset x=%d y=%d\n",
+        ALOGV("Content area is %ux%u at offset x=%d y=%d\n",
                 outWidth, outHeight, offX, offY);
     }
 
@@ -123,6 +123,7 @@
 
     Mutex::Autolock _l(mMutex);
 
+    ALOGV("Orientation: %d", mainDpyInfo.orientation);
     mRotate = isDeviceRotated(mainDpyInfo.orientation);
     mWidth = mRotate ? mainDpyInfo.h : mainDpyInfo.w;
     mHeight = mRotate ? mainDpyInfo.w : mainDpyInfo.h;
@@ -195,51 +196,14 @@
 status_t VirtualDisplay::setup_l() {
     status_t err;
 
-    err = mEglWindow.createPbuffer(mWidth, mHeight);
-    if (err != NO_ERROR) {
-        return err;
-    }
-    mEglWindow.makeCurrent();
-
-    glViewport(0, 0, mWidth, mHeight);
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_CULL_FACE);
-
-    // Shader for rendering the external texture.
-    err = mExtTexProgram.setup(Program::PROGRAM_EXTERNAL_TEXTURE);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    // Input side (buffers from virtual display).
-    glGenTextures(1, &mExtTextureName);
-    if (mExtTextureName == 0) {
-        ALOGE("glGenTextures failed: %#x", glGetError());
-        return UNKNOWN_ERROR;
-    }
-
-    mBufSize = mWidth * mHeight * kGlBytesPerPixel;
-
-    // pixel buffer for image copy
-    mPBO = new GLuint[NUM_PBO];
-    glGenBuffers(NUM_PBO, mPBO);
-
-    for (unsigned int i = 0; i < NUM_PBO; i++) {
-        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[i]);
-        glBufferData(GL_PIXEL_PACK_BUFFER, mBufSize, 0, GL_DYNAMIC_READ);
-        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-    }
-
     sp<IGraphicBufferConsumer> consumer;
     BufferQueue::createBufferQueue(&mProducer, &consumer);
-    mGlConsumer = new GLConsumer(consumer, mExtTextureName,
-                GL_TEXTURE_EXTERNAL_OES, true, false);
-    mGlConsumer->setName(String8("virtual display"));
-    mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
+    mCpuConsumer = new CpuConsumer(consumer, 1);
+    mCpuConsumer->setName(String8("vds-to-cpu"));
+    mCpuConsumer->setDefaultBufferSize(mWidth, mHeight);
     mProducer->setMaxDequeuedBufferCount(4);
-    mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
 
-    mGlConsumer->setFrameAvailableListener(this);
+    mCpuConsumer->setFrameAvailableListener(this);
 
     ALOGD("VirtualDisplay::setup_l OK");
     return NO_ERROR;
@@ -248,60 +212,42 @@
 void* VirtualDisplay::processFrame_l() {
     ALOGD("processFrame_l\n");
 
-    float texMatrix[16];
-    mGlConsumer->updateTexImage();
-    mGlConsumer->getTransformMatrix(texMatrix);
+    mUpdateMutex->lock();
 
-    int64_t startWhen, blitWhen, readWhen, mapWhen, memcpyWhen, markWhen;
-    startWhen = systemTime(CLOCK_MONOTONIC);
-
-    // The data is in an external texture, so we need to render it to the
-    // pbuffer to get access to RGB pixel data.  We also want to flip it
-    // upside-down for easy conversion to a bitmap.
-    int width = mEglWindow.getWidth();
-    int height = mEglWindow.getHeight();
-    mExtTexProgram.blit(mExtTextureName, texMatrix, 0, 0, mWidth, mHeight, true);
-
-    blitWhen = systemTime(CLOCK_MONOTONIC);
-
-    GLenum glErr;
-    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[mIndex]);
-    glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-    if ((glErr = glGetError()) != GL_NO_ERROR) {
-        ALOGE("glReadPixels failed: %#x", glErr);
-        return NULL;
+    CpuConsumer::LockedBuffer imgBuffer;
+    status_t res = mCpuConsumer->lockNextBuffer(&imgBuffer);
+    if (res != OK) {
+        ALOGE("Failed to lock next buffer: %s (%d)", strerror(-res), res);
+        return nullptr;
     }
 
-    readWhen = systemTime(CLOCK_MONOTONIC);
+    ALOGV("imgBuffer ptr: %p format: %x (%dx%d, stride=%d)", imgBuffer.data, imgBuffer.format, imgBuffer.width, imgBuffer.height, imgBuffer.stride);
 
-    void* ptr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, mBufSize, GL_MAP_READ_BIT);
-    mapWhen = systemTime(CLOCK_MONOTONIC);
-    //memcpy(mVNCScreen->frameBuffer, ptr, mBufSize);
-    mVNCScreen->frameBuffer = (char *)ptr;
-    memcpyWhen = systemTime(CLOCK_MONOTONIC);
+    void* vncbuf = mVNCScreen->frameBuffer;
+    void* imgbuf = imgBuffer.data;
+
+    for (size_t y = 0; y < mHeight; y++) {
+        memcpy(vncbuf, imgbuf, mWidth * 4);
+        vncbuf = (void *)((char *)vncbuf + mWidth * 4);
+        imgbuf = (void *)((char *)imgbuf + imgBuffer.stride * 4);
+    }
+    ALOGD("buf copied");
+    
+    mVNCScreen->frameBuffer = (char *)imgBuffer.data;
+    mVNCScreen->paddedWidthInBytes = imgBuffer.stride * 4;
     rfbMarkRectAsModified(mVNCScreen, 0, 0, mWidth, mHeight);
-    markWhen = systemTime(CLOCK_MONOTONIC);
 
-    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
-    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 
-    ALOGV("processFrame: blit=%.3fms read=%.3fms map=%.3fms memcpy=%.3fms mark=%.3fms",
-            (blitWhen - startWhen) / 1000000.0,
-            (readWhen - blitWhen) / 1000000.0,
-            (mapWhen - readWhen) / 1000000.0,
-            (memcpyWhen - mapWhen) / 1000000.0,
-            (markWhen - memcpyWhen) / 1000000.0);
+    mCpuConsumer->unlockBuffer(imgBuffer);
+    mUpdateMutex->unlock();
 
-    mIndex = (mIndex + 1) % NUM_PBO;
-    return mVNCScreen->frameBuffer;
+    return nullptr;
 }
 
 void VirtualDisplay::release_l() {
     ALOGD("release_l");
-    mGlConsumer.clear();
+    mCpuConsumer.clear();
     mProducer.clear();
-    mExtTexProgram.release();
-    mEglWindow.release();
     SurfaceComposerClient::destroyDisplay(mDpy);
 }
 
diff --git a/src/VirtualDisplay.h b/src/VirtualDisplay.h
index 90f1138..57c2c92 100644
--- a/src/VirtualDisplay.h
+++ b/src/VirtualDisplay.h
@@ -17,11 +17,8 @@
 #ifndef VDS_H
 #define VDS_H
 
-#include "Program.h"
-#include "EglWindow.h"
-
 #include <gui/BufferQueue.h>
-#include <gui/GLConsumer.h>
+#include <gui/CpuConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <ui/DisplayInfo.h>
 #include <utils/Thread.h>
@@ -35,13 +32,13 @@
 /*
  * Support for "frames" output format.
  */
-class VirtualDisplay : public GLConsumer::FrameAvailableListener, Thread {
+class VirtualDisplay : public CpuConsumer::FrameAvailableListener, Thread {
 public:
-    VirtualDisplay(rfbScreenInfoPtr vncScreen) : Thread(false),
+    VirtualDisplay(rfbScreenInfoPtr vncScreen, Mutex *updateMutex) : Thread(false),
         mVNCScreen(vncScreen),
+        mUpdateMutex(updateMutex),
         mThreadResult(UNKNOWN_ERROR),
-        mState(UNINITIALIZED),
-        mIndex(0)
+        mState(UNINITIALIZED)
         {}
 
     // Create an "input surface", similar in purpose to a MediaCodec input
@@ -81,6 +78,7 @@
     void* processFrame_l();
 
     rfbScreenInfoPtr mVNCScreen;
+    Mutex *mUpdateMutex;
 
     uint32_t mHeight, mWidth;
     bool mRotate;
@@ -107,22 +105,7 @@
     sp<IGraphicBufferProducer> mProducer;
 
     // This receives frames from the virtual display and makes them available
-    // as an external texture.
-    sp<GLConsumer> mGlConsumer;
-
-    // EGL display / context / surface.
-    EglWindow mEglWindow;
-
-    // GL rendering support.
-    Program mExtTexProgram;
-
-    // External texture, updated by GLConsumer.
-    GLuint mExtTextureName;
-
-    // Pixel data buffers.
-    size_t mBufSize;
-    GLuint* mPBO;
-    unsigned int mIndex;
+    sp<CpuConsumer> mCpuConsumer;
 
     sp<IBinder> mDpy;
 };