vnc: Static scaling support
* Add new commandline flag to apply a static scaling multiplier.
* The scaling is applied in hardware for best performance.
* This does not yet apply as a result of rfbSetScale calls
(window resize) from clients.
* Fix server shutdown too.
diff --git a/src/VNCFlinger.cpp b/src/VNCFlinger.cpp
index cd7da0f..b9b5da4 100644
--- a/src/VNCFlinger.cpp
+++ b/src/VNCFlinger.cpp
@@ -26,6 +26,8 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
+#include <ui/PixelFormat.h>
+
#include "InputDevice.h"
#include "VNCFlinger.h"
@@ -33,6 +35,7 @@
VNCFlinger::VNCFlinger() {
mOrientation = -1;
+ mScale = 1.0f;
mMainDpy = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
updateDisplayProjection();
@@ -53,7 +56,6 @@
}
status_t VNCFlinger::setV6Address(const String8& address) {
- ALOGD("v6: %s", const_cast<char *>(address.string()));
mVNCScreen->listen6Interface = const_cast<char *>(address.string());
return NO_ERROR;
}
@@ -72,6 +74,15 @@
return NO_ERROR;
}
+status_t VNCFlinger::setScale(float scale) {
+ if (scale <= 0.0f || scale > 2.0f) {
+ return BAD_VALUE;
+ }
+ mScale = scale;
+ updateDisplayProjection();
+ return NO_ERROR;
+}
+
status_t VNCFlinger::clearPassword() {
std::remove(VNC_AUTH_FILE);
ALOGW("Password authentication disabled");
@@ -112,12 +123,12 @@
status_t VNCFlinger::stop() {
Mutex::Autolock _L(mEventMutex);
-
ALOGV("Shutting down");
- rfbShutdownServer(mVNCScreen, true);
+ rfbShutdownServer(mVNCScreen, false);
destroyVirtualDisplayLocked();
+
mClientCount = 0;
mRunning = false;
@@ -167,7 +178,8 @@
mCpuConsumer = new CpuConsumer(consumer, NUM_BUFS);
mCpuConsumer->setName(String8("vds-to-cpu"));
mCpuConsumer->setDefaultBufferSize(mWidth, mHeight);
- mProducer->setMaxDequeuedBufferCount(4);
+ mProducer->setMaxDequeuedBufferCount(1);
+ consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBX_8888);
mListener = new FrameListener(this);
mCpuConsumer->setFrameAvailableListener(mListener);
@@ -176,7 +188,9 @@
SurfaceComposerClient::openGlobalTransaction();
SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
- // setDisplayProjection(mDpy, mainDpyInfo);
+ Rect displayRect(0, 0, mSourceWidth, mSourceHeight);
+ Rect outRect(0, 0, mWidth, mHeight);
+ SurfaceComposerClient::setDisplayProjection(mDpy, 0, displayRect, outRect);
SurfaceComposerClient::setDisplayLayerStack(mDpy, 0); // default stack
SurfaceComposerClient::closeGlobalTransaction();
@@ -232,8 +246,9 @@
mVNCScreen->displayFinishedHook = (rfbDisplayFinishedHookPtr)VNCFlinger::onFrameDone;
mVNCScreen->serverFormat.trueColour = true;
mVNCScreen->serverFormat.bitsPerPixel = 32;
+ mVNCScreen->serverFormat.depth = 24;
mVNCScreen->handleEventsEagerly = true;
- mVNCScreen->deferUpdateTime = 1;
+ mVNCScreen->deferUpdateTime = 0;
mVNCScreen->screenData = this;
return err;
@@ -342,17 +357,25 @@
sourceWidth = info.h;
}
- if (mWidth == sourceWidth && mHeight == sourceHeight && mOrientation == info.orientation) {
+ uint32_t width = sourceWidth * mScale;
+ uint32_t height = sourceHeight * mScale;
+
+ if (mSourceWidth == sourceWidth && mSourceHeight == sourceHeight &&
+ mWidth == width && mHeight == height &&
+ mOrientation == info.orientation) {
return false;
}
- ALOGD("Display dimensions: %dx%d orientation=%d", sourceWidth, sourceHeight, info.orientation);
-
- // orientation change
- mWidth = sourceWidth;
- mHeight = sourceHeight;
+ // orientation / resolution change
+ mSourceWidth = sourceWidth;
+ mSourceHeight = sourceHeight;
+ mWidth = width;
+ mHeight = height;
mOrientation = info.orientation;
+ ALOGV("Dimensions: %dx%d [out: %dx%d, scale: %f] orientation=%d",
+ mSourceWidth, mSourceHeight, mWidth, mHeight, mScale, mOrientation);
+
if (!mVDSActive) {
return true;
}
@@ -361,6 +384,7 @@
// on the fly without forcing surfaceflinger to tear it down
destroyVirtualDisplayLocked();
createVirtualDisplay();
+
return false;
}
diff --git a/src/VNCFlinger.h b/src/VNCFlinger.h
index 856bbb7..3f9bf62 100644
--- a/src/VNCFlinger.h
+++ b/src/VNCFlinger.h
@@ -46,6 +46,7 @@
virtual status_t setPort(unsigned int port);
virtual status_t setV4Address(const String8& address);
virtual status_t setV6Address(const String8& address);
+ virtual status_t setScale(float scale);
virtual status_t clearPassword();
virtual status_t setPassword(const String8& passwd);
@@ -96,7 +97,9 @@
Condition mEventCond;
uint32_t mWidth, mHeight;
+ uint32_t mSourceWidth, mSourceHeight;
int32_t mOrientation;
+ float mScale;
size_t mClientCount;
diff --git a/src/main.cpp b/src/main.cpp
index e1e8ac1..322fcc0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -28,17 +28,19 @@
static sp<VNCFlinger> gVNC;
-static const char* const shortOpts = "4:6:p:s:vh";
+static const char* const shortOpts = "4:6:p:s:l:vh";
static const option longOpts[] = {
{"listen", 1, nullptr, '4'},
{"listen6", 1, nullptr, '6'},
{"port", 1, nullptr, 'p'},
{"password", 1, nullptr, 's'},
+ {"scale", 1, nullptr, 'l'},
{"version", 0, nullptr, 'v'},
{"help", 0, nullptr, 'h'},
};
-static void onSignal(int /* signal */) {
+static void onSignal(int signal) {
+ ALOGV("Shutting down on signal %d", signal);
gVNC->stop();
}
@@ -54,6 +56,7 @@
<< " -p <num> Port to listen on (default: 5900)\n"
<< " -s <pass> Store server password\n"
<< " -c Clear server password\n"
+ << " -l <scale> Scaling value (default: 1.0)\n"
<< " -v Show server version\n"
<< " -h Show help\n\n";
exit(1);
@@ -108,6 +111,13 @@
}
break;
+ case 'l':
+ if (gVNC->setScale(std::stof(optarg)) != OK) {
+ std::cerr << "Invalid scaling value (must be between 0.0 and 2.0)\n";
+ exit(1);
+ }
+ break;
+
case 'v':
printVersion();
break;
@@ -133,4 +143,5 @@
defaultServiceManager()->addService(String16("vnc"), new VNCService(gVNC));
gVNC->start();
+ gVNC.clear();
}