Refactor the code

 * Split out classes for pixel buffer and virtual display
 * Move resize handling to appropriate classes
 * Use callbacks for orientation change and client resize
 * Remove unnecessary locking
diff --git a/src/VirtualDisplay.cpp b/src/VirtualDisplay.cpp
new file mode 100644
index 0000000..8000f8f
--- /dev/null
+++ b/src/VirtualDisplay.cpp
@@ -0,0 +1,94 @@
+//
+// vncflinger - Copyright (C) 2017 Steve Kondik
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#define LOG_TAG "VirtualDisplay"
+#include <utils/Log.h>
+
+#include <gui/BufferQueue.h>
+#include <gui/CpuConsumer.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include "VirtualDisplay.h"
+
+using namespace vncflinger;
+
+VirtualDisplay::VirtualDisplay(DisplayInfo* info, uint32_t width, uint32_t height,
+                               sp<CpuConsumer::FrameAvailableListener> listener) {
+    mWidth = width;
+    mHeight = height;
+
+    if (info->orientation == DISPLAY_ORIENTATION_0 || info->orientation == DISPLAY_ORIENTATION_180) {
+        mSourceRect = Rect(info->w, info->h);
+    } else {
+        mSourceRect = Rect(info->h, info->w);
+    }
+
+    Rect displayRect = getDisplayRect();
+
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&mProducer, &consumer);
+    mCpuConsumer = new CpuConsumer(consumer, 1);
+    mCpuConsumer->setName(String8("vds-to-cpu"));
+    mCpuConsumer->setDefaultBufferSize(width, height);
+    mProducer->setMaxDequeuedBufferCount(4);
+    consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBX_8888);
+
+    mCpuConsumer->setFrameAvailableListener(listener);
+
+    mDpy = SurfaceComposerClient::createDisplay(String8("VNC-VirtualDisplay"), false /*secure*/);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    SurfaceComposerClient::setDisplaySurface(mDpy, mProducer);
+
+    SurfaceComposerClient::setDisplayProjection(mDpy, 0, mSourceRect, displayRect);
+    SurfaceComposerClient::setDisplayLayerStack(mDpy, 0);  // default stack
+    SurfaceComposerClient::closeGlobalTransaction();
+
+    ALOGV("Virtual display (%ux%u [viewport=%ux%u] created", width, height, displayRect.getWidth(),
+          displayRect.getHeight());
+}
+
+VirtualDisplay::~VirtualDisplay() {
+    mCpuConsumer.clear();
+    mProducer.clear();
+    SurfaceComposerClient::destroyDisplay(mDpy);
+
+    ALOGV("Virtual display destroyed");
+}
+
+Rect VirtualDisplay::getDisplayRect() {
+    uint32_t outWidth, outHeight;
+    if (mWidth > (uint32_t)((float)mWidth * aspectRatio())) {
+        // limited by narrow width; reduce height
+        outWidth = mWidth;
+        outHeight = (uint32_t)((float)mWidth * aspectRatio());
+    } else {
+        // limited by short height; restrict width
+        outHeight = mHeight;
+        outWidth = (uint32_t)((float)mHeight / aspectRatio());
+    }
+
+    // position the desktop in the viewport while preserving
+    // the source aspect ratio. we do this in case the client
+    // has resized the window and to deal with orientation
+    // changes set up by updateDisplayProjection
+    uint32_t offX, offY;
+    offX = (mWidth - outWidth) / 2;
+    offY = (mHeight - outHeight) / 2;
+    return Rect(offX, offY, offX + outWidth, offY + outHeight);
+}