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