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/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;
};