Skip to content

Commit

Permalink
Initial import of VNCFlinger
Browse files Browse the repository at this point in the history
  • Loading branch information
hyperb1iss committed Jun 12, 2017
0 parents commit 55db053
Show file tree
Hide file tree
Showing 14 changed files with 1,519 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
BasedOnStyle: Google
AllowShortBlocksOnASingleLine: false
AllowShortFunctionsOnASingleLine: false

AccessModifierOffset: -2
ColumnLimit: 100
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
IndentWidth: 4
PointerAlignment: Left
TabWidth: 4
UseTab: Never
PenaltyExcessCharacter: 32
43 changes: 43 additions & 0 deletions Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
src/EglWindow.cpp \
src/EventQueue.cpp \
src/Program.cpp \
src/VirtualDisplay.cpp \
src/VNCFlinger.cpp \
src/main.cpp

LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/src \
external/libvncserver \
external/zlib

LOCAL_SHARED_LIBRARIES := \
libbinder \
libcrypto \
libcutils \
libjpeg \
libgui \
libpng \
libssl \
libui \
libutils \
libz \
libEGL \
libGLESv2

LOCAL_STATIC_LIBRARIES += \
libvncserver

LOCAL_CFLAGS := -Ofast -Werror
LOCAL_CFLAGS += -DLOG_NDEBUG=0

#LOCAL_CXX := /usr/bin/include-what-you-use

LOCAL_MODULE := vncflinger
LOCAL_MODULE_TAGS := optional

include $(BUILD_EXECUTABLE)
189 changes: 189 additions & 0 deletions src/EglWindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* 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, 2,
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);
}
87 changes: 87 additions & 0 deletions src/EglWindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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*/
59 changes: 59 additions & 0 deletions src/EventQueue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#define LOG_TAG "VNC-EventQueue"
#include <utils/Log.h>

#include "EventQueue.h"

using namespace android;

void EventQueue::enqueue(const Event& event) {
mQueue.push(event);
ALOGV("enqueue: mId=%d mData=%p qlen=%zu", event.mId, event.mData, mQueue.size());

Mutex::Autolock _l(mMutex);
mCondition.broadcast();
}

void EventQueue::await() {
Mutex::Autolock _l(mMutex);

while (mRunning) {
ALOGV("begin wait");
mCondition.wait(mMutex);

ALOGV("queue active");
while (!mQueue.empty()) {
Event event = mQueue.front();
mQueue.pop();

mMutex.unlock();
for (std::vector<EventListener *>::iterator it = mListeners.begin();
it != mListeners.end(); ++it) {
ALOGV("call listener: %p", *it);
(*it)->onEvent(event);
}
mMutex.lock();

}
}
}

void EventQueue::shutdown() {
Mutex::Autolock _l(mMutex);
flush();
mRunning = false;
mCondition.broadcast();
}

void EventQueue::flush() {
Mutex::Autolock _l(mMutex);
mQueue = {};
}

void EventQueue::addListener(EventListener *listener) {
mListeners.push_back(listener);
ALOGV("addListener: %p", listener);
}

void EventQueue::removeListener(EventListener *listener) {
mListeners.erase(std::remove(mListeners.begin(), mListeners.end(), listener), mListeners.end());
}
Loading

0 comments on commit 55db053

Please sign in to comment.