-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 55db053
Showing
14 changed files
with
1,519 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} |
Oops, something went wrong.