Update minuitwrp graphics in line with latest minui

Note: events.cpp is still old code renamed to cpp to make it
easier to call functions like gr_fb_width().

I had to modify AOSP fbdev code to provide a separate memory
surface for drawing to as drawing directly to the framebuffer
resulted in rendering taking about 5 times longer.

I also modified AOSP adf code to provide a separate memory surface
for drawing for the same performance reasons. The Nexus 9 supports
adf graphics.

Overlay graphics work on at least one device. Overlay provides a
separate memory buffer already so performance is good.

I do not have a drm device yet that I know of. I made some attempt
to update the drm code to determine the correct pixel format based
on the drm graphics format, but what is available in pixel flinger
and what is available in drm do not line up all that well. Reports
are that the Pixel C is using drm graphics, but performance is
slow, likely due to the use of a mmap instead of a memory buffyer.

Change-Id: Ibd45bccca6ac2cb826037aa9b2aa5065cf683eed
diff --git a/data.cpp b/data.cpp
index 77e8f8d..07f9e61 100644
--- a/data.cpp
+++ b/data.cpp
@@ -59,9 +59,9 @@
 {
 	#include "twcommon.h"
 	#include "gui/pages.h"
-	#include "minuitwrp/minui.h"
 	void gui_notifyVarChange(const char *name, const char* value);
 }
+#include "minuitwrp/minui.h"
 
 #define FILE_VERSION 0x00010010
 
diff --git a/gui/action.cpp b/gui/action.cpp
index 8895e40..240db8f 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -43,15 +43,16 @@
 #include "../adb_install.h"
 #include "../fuse_sideload.h"
 #include "blanktimer.hpp"
+
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 #include "../variables.h"
 #include "../twinstall.h"
 #include "cutils/properties.h"
 #include "../adb_install.h"
 #include "../set_metadata.h"
 };
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/animation.cpp b/gui/animation.cpp
index 888b4ab..d45373d 100644
--- a/gui/animation.cpp
+++ b/gui/animation.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/blanktimer.cpp b/gui/blanktimer.cpp
index 06208e2..4662b1f 100644
--- a/gui/blanktimer.cpp
+++ b/gui/blanktimer.cpp
@@ -26,9 +26,9 @@
 #include "blanktimer.hpp"
 #include "../data.hpp"
 extern "C" {
-#include "../minuitwrp/minui.h"
 #include "../twcommon.h"
 }
+#include "../minuitwrp/minui.h"
 #include "../twrp-functions.hpp"
 #include "../variables.h"
 
@@ -71,7 +71,8 @@
 		PageManager::ChangeOverlay("lock");
 	}
 #ifndef TW_NO_SCREEN_BLANK
-	if (state == kOff && gr_fb_blank(1) >= 0) {
+	if (state == kOff) {
+		gr_fb_blank(true);
 		state = kBlanked;
 	}
 #endif
@@ -97,10 +98,7 @@
 	switch (state) {
 		case kBlanked:
 #ifndef TW_NO_SCREEN_BLANK
-			if (gr_fb_blank(0) < 0) {
-				LOGINFO("blanktimer::resetTimerAndUnblank failed to gr_fb_blank(0)\n");
-				break;
-			}
+			gr_fb_blank(false);
 #endif
 			// TODO: this is asymmetric with postscreenblank.sh - shouldn't it be under the next case label?
 			TWFunc::check_and_run_script("/sbin/postscreenunblank.sh", "unblank");
diff --git a/gui/button.cpp b/gui/button.cpp
index a4c1b52..45614e4 100644
--- a/gui/button.cpp
+++ b/gui/button.cpp
@@ -36,8 +36,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/checkbox.cpp b/gui/checkbox.cpp
index 1760bac..e79f0cd 100644
--- a/gui/checkbox.cpp
+++ b/gui/checkbox.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/console.cpp b/gui/console.cpp
index b5204fb..6f375ff 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -37,8 +37,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp
index a97ff34..23f235c 100644
--- a/gui/fileselector.cpp
+++ b/gui/fileselector.cpp
@@ -23,8 +23,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/fill.cpp b/gui/fill.cpp
index b315cd0..d0a1cfd 100644
--- a/gui/fill.cpp
+++ b/gui/fill.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 7cf21b0..f8a6a73 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -38,9 +38,9 @@
 extern "C"
 {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 #include <pixelflinger/pixelflinger.h>
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/image.cpp b/gui/image.cpp
index 8b43aaa..2107d55 100644
--- a/gui/image.cpp
+++ b/gui/image.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/input.cpp b/gui/input.cpp
index 68bd163..c12ecc2 100644
--- a/gui/input.cpp
+++ b/gui/input.cpp
@@ -39,8 +39,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -196,7 +196,7 @@
 			maskedValue += mMask;
 		displayValue = maskedValue;
 	}
-	textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+	textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 	if (textWidth <= mRenderW) {
 		lastX = x;
 		scrollingX = 0;
@@ -209,7 +209,7 @@
 	if (skipChars && skipChars < displayValue.size())
 		displayValue.erase(0, skipChars);
 
-	textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+	textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 	mRendered = false;
 
 	int deltaX, deltaText, newWidth;
@@ -222,11 +222,11 @@
 		if (mCursorLocation == -1) {
 			displayValue = originalValue;
 			skipChars = 0;
-			textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 			while (textWidth > mRenderW) {
 				displayValue.erase(0, 1);
 				skipChars++;
-				textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+				textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 			}
 			scrollingX = mRenderW - textWidth;
 			mInputText->SkipCharCount(skipChars);
@@ -237,12 +237,12 @@
 
 			cursorLocate = displayValue;
 			cursorLocate.resize(mCursorLocation);
-			textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+			textWidth = gr_ttf_measureEx(cursorLocate.c_str(), fontResource);
 			while (textWidth > mRenderW) {
 				skipChars++;
 				mCursorLocation--;
 				cursorLocate.erase(0, 1);
-				textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+				textWidth = gr_ttf_measureEx(cursorLocate.c_str(), fontResource);
 				adjust_scrollingX = -1;
 			}
 			if (adjust_scrollingX) {
@@ -261,7 +261,7 @@
 				}
 				insertChar = originalValue.substr(skipChars - 1, 1);
 				displayValue.insert(0, insertChar);
-				newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+				newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 				deltaText = newWidth - textWidth;
 				if (newWidth > mRenderW) {
 					scrollingX = mRenderW - textWidth;
@@ -289,7 +289,7 @@
 			}
 			insertChar = originalValue.substr(skipChars - 1, 1);
 			displayValue.insert(0, insertChar);
-			newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 			deltaText = newWidth - textWidth;
 			if (deltaText < deltaX) {
 				lastX += deltaText;
@@ -324,7 +324,7 @@
 			deltaX = lastX - x;
 			displayValue.erase(0, 1);
 			skipChars++;
-			newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 			deltaText = textWidth - newWidth;
 			if (newWidth <= mRenderW) {
 				scrollingX = mRenderW - newWidth;
@@ -407,15 +407,15 @@
 
 					cursorDisplay = displayValue;
 					cursorDisplay.resize(mCursorLocation);
-					cursorX = gr_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
+					cursorX = gr_ttf_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
 				} else {
 					// Cursor location is after the end of the text  - reset to -1
 					mCursorLocation = -1;
-					cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+					cursorX = gr_ttf_measureEx(displayValue.c_str(), fontResource) + mRenderX;
 				}
 			} else {
 				// Cursor is at the end (-1)
-				cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+				cursorX = gr_ttf_measureEx(displayValue.c_str(), fontResource) + mRenderX;
 			}
 		}
 		cursorX += scrollingX;
@@ -534,7 +534,7 @@
 			for(index=0; index<displayValue.size(); index++)
 			{
 				cursorString = displayValue.substr(0, index);
-				cursorX = gr_measureEx(cursorString.c_str(), fontResource) + mRenderX;
+				cursorX = gr_ttf_measureEx(cursorString.c_str(), fontResource) + mRenderX;
 				if (cursorX > x) {
 					if (index > 0)
 						mCursorLocation = index - 1;
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index 3b8fdc9..4a78ad7 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -25,9 +25,9 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 #include "gui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -333,7 +333,7 @@
 	else if (!labelText.empty())
 	{
 		void* fontResource = labelFont->GetResource();
-		int textW = gr_measureEx(labelText.c_str(), fontResource);
+		int textW = gr_ttf_measureEx(labelText.c_str(), fontResource);
 		int textH = labelFont->GetHeight();
 		int textX = keyX + (keyW - textW) / 2;
 		int textY = keyY + (keyH - textH) / 2;
@@ -347,7 +347,7 @@
 		gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha);
 		string text(1, keychar);
 		int textH = mLongpressFont->GetHeight();
-		int textW = gr_measureEx(text.c_str(), fontResource);
+		int textW = gr_ttf_measureEx(text.c_str(), fontResource);
 		int textX = keyX + keyW - longpressOffsetX - textW;
 		int textY = keyY + longpressOffsetY;
 		gr_textEx_scaleW(textX, textY, text.c_str(), fontResource, keyW, TOP_LEFT, 0);
diff --git a/gui/listbox.cpp b/gui/listbox.cpp
index b0d2731..e10fee7 100644
--- a/gui/listbox.cpp
+++ b/gui/listbox.cpp
@@ -20,8 +20,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/mousecursor.cpp b/gui/mousecursor.cpp
index 84e6322..bd730df 100644
--- a/gui/mousecursor.cpp
+++ b/gui/mousecursor.cpp
@@ -17,8 +17,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/pages.cpp b/gui/pages.cpp
index c455662..4a4c523 100644
--- a/gui/pages.cpp
+++ b/gui/pages.cpp
@@ -39,11 +39,11 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 #include "../minzip/SysUtil.h"
 #include "../minzip/Zip.h"
 #include "gui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/partitionlist.cpp b/gui/partitionlist.cpp
index 102802d..ff207fa 100644
--- a/gui/partitionlist.cpp
+++ b/gui/partitionlist.cpp
@@ -22,8 +22,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/patternpassword.cpp b/gui/patternpassword.cpp
index a6ab831..96054c1 100644
--- a/gui/patternpassword.cpp
+++ b/gui/patternpassword.cpp
@@ -13,8 +13,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/progressbar.cpp b/gui/progressbar.cpp
index a478a40..fc2a497 100644
--- a/gui/progressbar.cpp
+++ b/gui/progressbar.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/resources.cpp b/gui/resources.cpp
index a8f4199..e7611dd 100644
--- a/gui/resources.cpp
+++ b/gui/resources.cpp
@@ -14,9 +14,9 @@
 #include "../minzip/Zip.h"
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 #include "gui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/resources.hpp b/gui/resources.hpp
index ce06d96..4548c10 100644
--- a/gui/resources.hpp
+++ b/gui/resources.hpp
@@ -49,7 +49,7 @@
 
 public:
 	void* GetResource() { return this ? mFont : NULL; }
-	int GetHeight() { return gr_getMaxFontHeight(this ? mFont : NULL); }
+	int GetHeight() { return gr_ttf_getMaxFontHeight(this ? mFont : NULL); }
 	void Override(xml_node<>* node, ZipArchive* pZip);
 
 protected:
diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp
index 6e974f2..291b382 100644
--- a/gui/scrolllist.cpp
+++ b/gui/scrolllist.cpp
@@ -20,8 +20,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/slider.cpp b/gui/slider.cpp
index 6ee2024..59b295b 100644
--- a/gui/slider.cpp
+++ b/gui/slider.cpp
@@ -21,8 +21,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp
index 8a44a3c..088620a 100644
--- a/gui/slidervalue.cpp
+++ b/gui/slidervalue.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -249,7 +249,7 @@
 	void* fontResource = NULL;
 	if (mFont)  fontResource = mFont->GetResource();
 
-	return gr_measureEx(str.c_str(), fontResource);
+	return gr_ttf_measureEx(str.c_str(), fontResource);
 }
 
 int GUISliderValue::Render(void)
diff --git a/gui/terminal.cpp b/gui/terminal.cpp
index 044782e..29b0e84 100644
--- a/gui/terminal.cpp
+++ b/gui/terminal.cpp
@@ -32,8 +32,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -869,10 +869,10 @@
 		// render cursor
 		int cursorX = engine->getCursorX();
 		std::string leftOfCursor = line.substr(0, cursorX);
-		int x = gr_measureEx(leftOfCursor.c_str(), mFont->GetResource());
+		int x = gr_ttf_measureEx(leftOfCursor.c_str(), mFont->GetResource());
 		// note that this single character can be a UTF-8 sequence
 		std::string atCursor = (size_t)cursorX < line.length() ? line.substr(cursorX, 1) : " ";
-		int w = gr_measureEx(atCursor.c_str(), mFont->GetResource());
+		int w = gr_ttf_measureEx(atCursor.c_str(), mFont->GetResource());
 		gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
 		gr_fill(mRenderX + x, yPos, w, actualItemHeight);
 		gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha);
@@ -890,7 +890,7 @@
 	// make sure the shell is started
 	engine->initPty();
 	// send window resize
-	int charWidth = gr_measureEx("N", mFont->GetResource());
+	int charWidth = gr_ttf_measureEx("N", mFont->GetResource());
 	engine->setSize(mRenderW / charWidth, GetDisplayItemCount(), mRenderW, mRenderH);
 }
 
diff --git a/gui/text.cpp b/gui/text.cpp
index 9898e28..6498af6 100644
--- a/gui/text.cpp
+++ b/gui/text.cpp
@@ -19,8 +19,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -47,6 +47,8 @@
 
 	// Load the font, and possibly override the color
 	mFont = LoadAttrFont(FindNode(node, "font"), "resource");
+	if (!mFont)
+		return;
 	mColor = LoadAttrColor(FindNode(node, "font"), "color", mColor);
 	mHighlightColor = LoadAttrColor(FindNode(node, "font"), "highlightcolor", mColor);
 
@@ -88,6 +90,8 @@
 	void* fontResource = NULL;
 	if (mFont)
 		fontResource = mFont->GetResource();
+	else
+		return -1;
 
 	mLastValue = gui_parse_text(mText);
 	string displayValue = mLastValue;
@@ -98,7 +102,7 @@
 	mVarChanged = 0;
 
 	int x = mRenderX, y = mRenderY;
-	int width = gr_measureEx(displayValue.c_str(), fontResource);
+	int width = gr_ttf_measureEx(displayValue.c_str(), fontResource);
 
 	if (isHighlighted)
 		gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
@@ -145,7 +149,7 @@
 
 	h = mFontHeight;
 	mLastValue = gui_parse_text(mText);
-	w = gr_measureEx(mLastValue.c_str(), fontResource);
+	w = gr_ttf_measureEx(mLastValue.c_str(), fontResource);
 	return 0;
 }
 
diff --git a/gui/textbox.cpp b/gui/textbox.cpp
index 277297f..2e2512c 100644
--- a/gui/textbox.cpp
+++ b/gui/textbox.cpp
@@ -22,8 +22,8 @@
 
 extern "C" {
 #include "../twcommon.h"
-#include "../minuitwrp/minui.h"
 }
+#include "../minuitwrp/minui.h"
 
 #include "rapidxml.hpp"
 #include "objects.hpp"
@@ -86,7 +86,7 @@
 
 	// render text
 	const char* text = rText[itemindex].c_str();
-	gr_textEx(mRenderX, yPos, text, mFont->GetResource());
+	gr_textEx_scaleW(mRenderX, yPos, text, mFont->GetResource(), mRenderW, TOP_LEFT, 0);
 }
 
 void GUITextBox::NotifySelect(size_t item_selected __unused)
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index 01225c3..39c61c4 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -2,12 +2,20 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := events.c resources.c graphics_overlay.c graphics_utils.c truetype.c
+LOCAL_SRC_FILES := \
+    graphics.cpp \
+    graphics_fbdev.cpp \
+    resources.cpp \
+    graphics_overlay.cpp \
+    truetype.cpp \
+    graphics_utils.cpp \
+    events.cpp
 
 ifneq ($(TW_BOARD_CUSTOM_GRAPHICS),)
-    LOCAL_SRC_FILES += $(TW_BOARD_CUSTOM_GRAPHICS)
-else
-    LOCAL_SRC_FILES += graphics.c
+    $(warning ****************************************************************************)
+    $(warning * TW_BOARD_CUSTOM_GRAPHICS support has been deprecated in TWRP.            *)
+    $(warning ****************************************************************************)
+    $(error stopping)
 endif
 
 ifeq ($(TW_TARGET_USES_QCOM_BSP), true)
@@ -17,25 +25,39 @@
     LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
   else
     ifeq ($(TARGET_CUSTOM_KERNEL_HEADERS),)
-      LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minuitwrp/include
+      LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minui/include
     else
       LOCAL_C_INCLUDES += $(TARGET_CUSTOM_KERNEL_HEADERS)
     endif
   endif
 else
-  LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minuitwrp/include
+  LOCAL_C_INCLUDES += $(commands_recovery_local_path)/minui/include
+  # The header files required for adf graphics can cause compile errors
+  # with adf graphics.
+  ifneq ($(wildcard system/core/adf/Android.mk),)
+    LOCAL_CFLAGS += -DHAS_ADF
+    LOCAL_SRC_FILES += graphics_adf.cpp
+    LOCAL_WHOLE_STATIC_LIBRARIES += libadf
+  endif
 endif
 
 ifeq ($(TW_NEW_ION_HEAP), true)
   LOCAL_CFLAGS += -DNEW_ION_HEAP
 endif
 
+ifneq ($(wildcard external/libdrm/Android.mk),)
+  LOCAL_CFLAGS += -DHAS_DRM
+  LOCAL_SRC_FILES += graphics_drm.cpp
+  LOCAL_WHOLE_STATIC_LIBRARIES += libdrm
+endif
+
 LOCAL_C_INCLUDES += \
     external/libpng \
     external/zlib \
     system/core/include \
     external/jpeg \
-    external/freetype/include
+    external/freetype/include \
+    external/libcxx/include
 
 ifeq ($(RECOVERY_TOUCHSCREEN_SWAP_XY), true)
 LOCAL_CFLAGS += -DRECOVERY_TOUCHSCREEN_SWAP_XY
@@ -76,6 +98,12 @@
   LOCAL_CFLAGS += -DRECOVERY_RGB_565
 endif
 
+ifneq ($(TARGET_RECOVERY_OVERSCAN_PERCENT),)
+  LOCAL_CFLAGS += -DOVERSCAN_PERCENT=$(TARGET_RECOVERY_OVERSCAN_PERCENT)
+else
+  LOCAL_CFLAGS += -DOVERSCAN_PERCENT=0
+endif
+
 ifeq ($(TARGET_RECOVERY_PIXEL_FORMAT),"RGBX_8888")
   LOCAL_CFLAGS += -DRECOVERY_RGBX
 endif
@@ -120,6 +148,8 @@
     $(error stopping)
 endif
 
+LOCAL_CLANG := true
+
 LOCAL_CFLAGS += -DTWRES=\"$(TWRES_PATH)\"
 LOCAL_SHARED_LIBRARIES += libft2 libz libc libcutils libjpeg libpng libutils
 LOCAL_STATIC_LIBRARIES += libpixelflinger_twrp
diff --git a/minuitwrp/events.c b/minuitwrp/events.cpp
similarity index 99%
rename from minuitwrp/events.c
rename to minuitwrp/events.cpp
index 4e10e72..d4ca0ab 100644
--- a/minuitwrp/events.c
+++ b/minuitwrp/events.cpp
@@ -243,7 +243,7 @@
     printf("EV: MT minX: %d  maxX: %d  minY: %d  maxY: %d\n", e->mt_p.xi.minimum, e->mt_p.xi.maximum, e->mt_p.yi.minimum, e->mt_p.yi.maximum);
 #endif
 
-    e->vks = malloc(sizeof(*e->vks) * e->vk_count);
+    e->vks = (virtualkey *)malloc(sizeof(*e->vks) * e->vk_count);
 
     for (i = 0; i < e->vk_count; ++i) {
         char *token[6];
diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c
deleted file mode 100644
index fb86c14..0000000
--- a/minuitwrp/graphics.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <linux/fb.h>
-#include <linux/kd.h>
-
-#include <pixelflinger/pixelflinger.h>
-
-#include "minui.h"
-#include "../gui/placement.h"
-
-#ifdef RECOVERY_BGRA
-#define PIXEL_FORMAT GGL_PIXEL_FORMAT_BGRA_8888
-#define PIXEL_SIZE 4
-#endif
-#ifdef RECOVERY_RGBA
-#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBA_8888
-#define PIXEL_SIZE   4
-#endif
-#ifdef RECOVERY_RGBX
-#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGBX_8888
-#define PIXEL_SIZE 4
-#endif
-#ifndef PIXEL_FORMAT
-#define PIXEL_FORMAT GGL_PIXEL_FORMAT_RGB_565
-#define PIXEL_SIZE 2
-#endif
-
-#define NUM_BUFFERS 2
-#define MAX_DISPLAY_DIM  2048
-
-// #define PRINT_SCREENINFO 1 // Enables printing of screen info to log
-
-typedef struct {
-    int type;
-    GGLSurface texture;
-    unsigned offset[97];
-    unsigned cheight;
-    unsigned ascent;
-} GRFont;
-
-static GRFont *gr_font = 0;
-static GGLContext *gr_context = 0;
-static GGLSurface gr_font_texture;
-static GGLSurface gr_framebuffer[NUM_BUFFERS];
-GGLSurface gr_mem_surface;
-static unsigned gr_active_fb = 0;
-static unsigned double_buffering = 0;
-static int gr_is_curr_clr_opaque = 0;
-
-static int gr_fb_fd = -1;
-static int gr_vt_fd = -1;
-
-struct fb_var_screeninfo vi;
-static struct fb_fix_screeninfo fi;
-
-static bool has_overlay = false;
-static int leftSplit = 0;
-static int rightSplit = 0;
-
-bool target_has_overlay(char *version);
-int free_ion_mem(void);
-int alloc_ion_mem(unsigned int size);
-int allocate_overlay(int fd, GGLSurface gr_fb[]);
-int free_overlay(int fd);
-int overlay_display_frame(int fd, GGLubyte* data, size_t size);
-
-#ifdef PRINT_SCREENINFO
-static void print_fb_var_screeninfo()
-{
-    printf("vi.xres: %d\n", vi.xres);
-    printf("vi.yres: %d\n", vi.yres);
-    printf("vi.xres_virtual: %d\n", vi.xres_virtual);
-    printf("vi.yres_virtual: %d\n", vi.yres_virtual);
-    printf("vi.xoffset: %d\n", vi.xoffset);
-    printf("vi.yoffset: %d\n", vi.yoffset);
-    printf("vi.bits_per_pixel: %d\n", vi.bits_per_pixel);
-    printf("vi.grayscale: %d\n", vi.grayscale);
-}
-#endif
-
-#ifdef MSM_BSP
-int getLeftSplit(void) {
-   //Default even split for all displays with high res
-   int lSplit = vi.xres / 2;
-
-   //Override if split published by driver
-   if (leftSplit)
-       lSplit = leftSplit;
-
-   return lSplit;
-}
-
-int getRightSplit(void) {
-   return rightSplit;
-}
-
-
-void setDisplaySplit(void) {
-    char split[64] = {0};
-    FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
-    if (fp) {
-        //Format "left right" space as delimiter
-        if(fread(split, sizeof(char), 64, fp)) {
-            leftSplit = atoi(split);
-            printf("Left Split=%d\n",leftSplit);
-            char *rght = strpbrk(split, " ");
-            if (rght)
-                rightSplit = atoi(rght + 1);
-            printf("Right Split=%d\n", rightSplit);
-        }
-    } else {
-        printf("Failed to open mdss_fb_split node\n");
-    }
-    if (fp)
-        fclose(fp);
-}
-
-bool isDisplaySplit(void) {
-    if (vi.xres > MAX_DISPLAY_DIM)
-        return true;
-    //check if right split is set by driver
-    if (getRightSplit())
-        return true;
-
-    return false;
-}
-
-int getFbXres(void) {
-    return vi.xres;
-}
-
-int getFbYres (void) {
-    return vi.yres;
-}
-#endif // MSM_BSP
-
-static int get_framebuffer(GGLSurface *fb)
-{
-    int fd, index = 0;
-    void *bits;
-
-    fd = open("/dev/graphics/fb0", O_RDWR);
-    
-    while (fd < 0 && index < 30) {
-        usleep(1000);
-        fd = open("/dev/graphics/fb0", O_RDWR);
-        index++;
-    }
-    if (fd < 0) {
-        perror("cannot open fb0\n");
-        return -1;
-    }
-
-    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
-        perror("failed to get fb0 info");
-        close(fd);
-        return -1;
-    }
-
-    fprintf(stderr, "Pixel format: %dx%d @ %dbpp\n", vi.xres, vi.yres, vi.bits_per_pixel);
-
-    vi.bits_per_pixel = PIXEL_SIZE * 8;
-    if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_BGRA_8888) {
-        fprintf(stderr, "Pixel format: BGRA_8888\n");
-        if (PIXEL_SIZE != 4)    fprintf(stderr, "E: Pixel Size mismatch!\n");
-        vi.red.offset     = 8;
-        vi.red.length     = 8;
-        vi.green.offset   = 16;
-        vi.green.length   = 8;
-        vi.blue.offset    = 24;
-        vi.blue.length    = 8;
-        vi.transp.offset  = 0;
-        vi.transp.length  = 8;
-    } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBA_8888) {
-        fprintf(stderr, "Pixel format: RGBA_8888\n");
-        if (PIXEL_SIZE != 4)    fprintf(stderr, "E: Pixel Size mismatch!\n");
-        vi.red.offset     = 0;
-        vi.red.length     = 8;
-        vi.green.offset   = 8;
-        vi.green.length   = 8;
-        vi.blue.offset    = 16;
-        vi.blue.length    = 8;
-        vi.transp.offset  = 24;
-        vi.transp.length  = 8;
-    } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGBX_8888) {
-        fprintf(stderr, "Pixel format: RGBX_8888\n");
-        if (PIXEL_SIZE != 4)    fprintf(stderr, "E: Pixel Size mismatch!\n");
-        vi.red.offset     = 24;
-        vi.red.length     = 8;
-        vi.green.offset   = 16;
-        vi.green.length   = 8;
-        vi.blue.offset    = 8;
-        vi.blue.length    = 8;
-        vi.transp.offset  = 0;
-        vi.transp.length  = 8;
-    } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGB_565) {
-#ifdef RECOVERY_RGB_565
-        fprintf(stderr, "Pixel format: RGB_565\n");
-        vi.blue.offset    = 0;
-        vi.green.offset   = 5;
-        vi.red.offset     = 11;
-#else
-        fprintf(stderr, "Pixel format: BGR_565\n");
-        vi.blue.offset    = 11;
-        vi.green.offset   = 5;
-        vi.red.offset     = 0;
-#endif
-        if (PIXEL_SIZE != 2)    fprintf(stderr, "E: Pixel Size mismatch!\n");
-        vi.blue.length    = 5;
-        vi.green.length   = 6;
-        vi.red.length     = 5;
-        vi.blue.msb_right = 0;
-        vi.green.msb_right = 0;
-        vi.red.msb_right = 0;
-        vi.transp.offset  = 0;
-        vi.transp.length  = 0;
-    }
-    else
-    {
-        perror("unknown pixel format");
-        close(fd);
-        return -1;
-    }
-
-    vi.vmode = FB_VMODE_NONINTERLACED;
-    vi.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
-
-    if (ioctl(fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
-        perror("failed to put fb0 info");
-        close(fd);
-        return -1;
-    }
-
-    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
-        perror("failed to get fb0 info");
-        close(fd);
-        return -1;
-    }
-
-#ifdef MSM_BSP
-    has_overlay = target_has_overlay(fi.id);
-
-    if (isTargetMdp5())
-        setDisplaySplit();
-#else
-    has_overlay = false;
-#endif
-
-    if (!has_overlay) {
-        printf("Not using qualcomm overlay, '%s'\n", fi.id);
-        bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-        if (bits == MAP_FAILED) {
-            perror("failed to mmap framebuffer");
-            close(fd);
-            return -1;
-        }
-    } else {
-        printf("Using qualcomm overlay\n");
-    }
-
-#ifdef RECOVERY_GRAPHICS_USE_LINELENGTH
-    vi.xres_virtual = fi.line_length / PIXEL_SIZE;
-#endif
-
-    fb->version = sizeof(*fb);
-    fb->width = vi.xres;
-    fb->height = vi.yres;
-#ifdef BOARD_HAS_JANKY_BACKBUFFER
-    printf("setting JANKY BACKBUFFER\n");
-    fb->stride = fi.line_length/2;
-#else
-    fb->stride = vi.xres_virtual;
-#endif
-    fb->format = PIXEL_FORMAT;
-    if (!has_overlay) {
-        fb->data = bits;
-        memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE);
-    }
-
-    fb++;
-
-#ifndef TW_DISABLE_DOUBLE_BUFFERING
-    /* check if we can use double buffering */
-    if (vi.yres * fi.line_length * 2 > fi.smem_len)
-#else
-    printf("TW_DISABLE_DOUBLE_BUFFERING := true\n");
-#endif
-        return fd;
-
-    double_buffering = 1;
-
-    fb->version = sizeof(*fb);
-    fb->width = vi.xres;
-    fb->height = vi.yres;
-#ifdef BOARD_HAS_JANKY_BACKBUFFER
-    fb->stride = fi.line_length/2;
-    fb->data = (GGLubyte*) (((unsigned long) bits) + vi.yres * fi.line_length);
-#else
-    fb->stride = vi.xres_virtual;
-    fb->data = (GGLubyte*) (((unsigned long) bits) + vi.yres * fb->stride * PIXEL_SIZE);
-#endif
-    fb->format = PIXEL_FORMAT;
-    if (!has_overlay) {
-        memset(fb->data, 0, vi.yres * fb->stride * PIXEL_SIZE);
-    }
-
-#ifdef PRINT_SCREENINFO
-    print_fb_var_screeninfo();
-#endif
-
-    return fd;
-}
-
-static void get_memory_surface(GGLSurface* ms) {
-  ms->version = sizeof(*ms);
-  ms->width = vi.xres;
-  ms->height = vi.yres;
-  ms->stride = vi.xres_virtual;
-  ms->data = malloc(vi.xres_virtual * vi.yres * PIXEL_SIZE);
-  ms->format = PIXEL_FORMAT;
-}
-
-static void set_active_framebuffer(unsigned n)
-{
-    if (n > 1  || !double_buffering) return;
-    vi.yres_virtual = vi.yres * NUM_BUFFERS;
-    vi.yoffset = n * vi.yres;
-//    vi.bits_per_pixel = PIXEL_SIZE * 8;
-    if (ioctl(gr_fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
-        perror("active fb swap failed");
-    }
-}
-
-void gr_flip(void)
-{
-    if (-EINVAL == overlay_display_frame(gr_fb_fd, gr_mem_surface.data,
-                                         (fi.line_length * vi.yres))) {
-        GGLContext *gl = gr_context;
-
-        /* swap front and back buffers */
-        if (double_buffering)
-            gr_active_fb = (gr_active_fb + 1) & 1;
-
-#ifdef BOARD_HAS_FLIPPED_SCREEN
-        /* flip buffer 180 degrees for devices with physicaly inverted screens */
-        unsigned int i;
-        unsigned int j;
-        for (i = 0; i < vi.yres; i++) {
-            for (j = 0; j < vi.xres; j++) {
-                memcpy(gr_framebuffer[gr_active_fb].data + (i * vi.xres_virtual + j) * PIXEL_SIZE,
-                       gr_mem_surface.data + ((vi.yres - i - 1) * vi.xres_virtual + vi.xres - j - 1) * PIXEL_SIZE, PIXEL_SIZE);
-            }
-        }
-#else
-        /* copy data from the in-memory surface to the buffer we're about
-         * to make active. */
-        memcpy(gr_framebuffer[gr_active_fb].data, gr_mem_surface.data,
-               vi.xres_virtual * vi.yres * PIXEL_SIZE);
-#endif
-
-        /* inform the display driver */
-        set_active_framebuffer(gr_active_fb);
-    }
-}
-
-void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
-{
-    GGLContext *gl = gr_context;
-    GGLint color[4];
-    color[0] = ((r << 8) | r) + 1;
-    color[1] = ((g << 8) | g) + 1;
-    color[2] = ((b << 8) | b) + 1;
-    color[3] = ((a << 8) | a) + 1;
-    gl->color4xv(gl, color);
-
-    gr_is_curr_clr_opaque = (a == 255);
-}
-
-int gr_measureEx(const char *s, void* font)
-{
-    GRFont* fnt = (GRFont*) font;
-
-    if (!fnt)
-        return 0;
-
-    return gr_ttf_measureEx(s, font);
-}
-
-int gr_maxExW(const char *s, void* font, int max_width)
-{
-    GRFont* fnt = (GRFont*) font;
-
-    if (!fnt)
-        return 0;
-
-    return gr_ttf_maxExW(s, font, max_width);
-}
-
-int gr_textEx(int x, int y, const char *s, void* pFont)
-{
-    GGLContext *gl = gr_context;
-    GRFont *font = (GRFont*) pFont;
-
-    if (!font)
-        return 0;
-
-    return gr_ttf_textExWH(gl, x, y, s, pFont, -1, -1);
-}
-
-int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale)
-{
-    GGLContext *gl = gr_context;
-    void* vfont = pFont;
-    GRFont *font = (GRFont*) pFont;
-    unsigned off;
-    unsigned cwidth;
-    int y_scale = 0, measured_width, measured_height, ret, new_height;
-
-    if (!s || strlen(s) == 0 || !font)
-        return 0;
-
-    measured_height = gr_ttf_getMaxFontHeight(font);
-
-    if (scale) {
-        measured_width = gr_ttf_measureEx(s, vfont);
-        if (measured_width > max_width) {
-            // Adjust font size down until the text fits
-            void *new_font = gr_ttf_scaleFont(vfont, max_width, measured_width);
-            if (!new_font) {
-                printf("gr_textEx_scaleW new_font is NULL\n");
-                return 0;
-            }
-            measured_width = gr_ttf_measureEx(s, new_font);
-            // These next 2 lines adjust the y point based on the new font's height
-            new_height = gr_ttf_getMaxFontHeight(new_font);
-            y_scale = (measured_height - new_height) / 2;
-            vfont = new_font;
-        }
-    } else
-        measured_width = gr_ttf_measureEx(s, vfont);
-
-    int x_adj = measured_width;
-    if (measured_width > max_width)
-        x_adj = max_width;
-
-    if (placement != TOP_LEFT && placement != BOTTOM_LEFT && placement != TEXT_ONLY_RIGHT) {
-        if (placement == CENTER || placement == CENTER_X_ONLY)
-            x -= (x_adj / 2);
-        else
-            x -= x_adj;
-    }
-
-    if (placement != TOP_LEFT && placement != TOP_RIGHT) {
-        if (placement == CENTER || placement == TEXT_ONLY_RIGHT)
-            y -= (measured_height / 2);
-        else if (placement == BOTTOM_LEFT || placement == BOTTOM_RIGHT)
-            y -= measured_height;
-    }
-    return gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1);
-}
-
-int gr_textExW(int x, int y, const char *s, void* pFont, int max_width)
-{
-    GGLContext *gl = gr_context;
-    GRFont *font = (GRFont*) pFont;
-
-    if (!font)
-        return 0;
-
-    return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, -1);
-}
-
-int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height)
-{
-    GGLContext *gl = gr_context;
-    GRFont *font = (GRFont*) pFont;
-
-    if (!font)
-        return 0;
-
-    return gr_ttf_textExWH(gl, x, y, s, pFont, max_width, max_height);
-}
-
-void gr_clip(int x, int y, int w, int h)
-{
-    GGLContext *gl = gr_context;
-    gl->scissor(gl, x, y, w, h);
-    gl->enable(gl, GGL_SCISSOR_TEST);
-}
-
-void gr_noclip()
-{
-    GGLContext *gl = gr_context;
-    gl->scissor(gl, 0, 0, gr_fb_width(), gr_fb_height());
-    gl->disable(gl, GGL_SCISSOR_TEST);
-}
-
-void gr_fill(int x, int y, int w, int h)
-{
-    GGLContext *gl = gr_context;
-
-    if(gr_is_curr_clr_opaque)
-        gl->disable(gl, GGL_BLEND);
-
-    gl->recti(gl, x, y, x + w, y + h);
-
-    if(gr_is_curr_clr_opaque)
-        gl->enable(gl, GGL_BLEND);
-}
-
-void gr_line(int x0, int y0, int x1, int y1, int width)
-{
-    GGLContext *gl = gr_context;
-
-    if(gr_is_curr_clr_opaque)
-        gl->disable(gl, GGL_BLEND);
-
-    const int coords0[2] = { x0 << 4, y0 << 4 };
-    const int coords1[2] = { x1 << 4, y1 << 4 };
-    gl->linex(gl, coords0, coords1, width << 4);
-
-    if(gr_is_curr_clr_opaque)
-        gl->enable(gl, GGL_BLEND);
-}
-
-gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
-{
-    int rx, ry;
-    GGLSurface *surface;
-    const int diameter = radius*2 + 1;
-    const int radius_check = radius*radius + radius*0.8;
-    const uint32_t px = (a << 24) | (b << 16) | (g << 8) | r;
-    uint32_t *data;
-
-    surface = malloc(sizeof(GGLSurface));
-    memset(surface, 0, sizeof(GGLSurface));
-
-    data = malloc(diameter * diameter * 4);
-    memset(data, 0, diameter * diameter * 4);
-
-    surface->version = sizeof(surface);
-    surface->width = diameter;
-    surface->height = diameter;
-    surface->stride = diameter;
-    surface->data = (GGLubyte*)data;
-    surface->format = GGL_PIXEL_FORMAT_RGBA_8888;
-
-    for(ry = -radius; ry <= radius; ++ry)
-        for(rx = -radius; rx <= radius; ++rx)
-            if(rx*rx+ry*ry <= radius_check)
-                *(data + diameter*(radius + ry) + (radius+rx)) = px;
-
-    return surface;
-}
-
-void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) {
-    if (gr_context == NULL) {
-        return;
-    }
-
-    GGLContext *gl = gr_context;
-    GGLSurface *surface = (GGLSurface*)source;
-
-    if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888)
-        gl->disable(gl, GGL_BLEND);
-
-    gl->bindTexture(gl, surface);
-    gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
-    gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
-    gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
-    gl->enable(gl, GGL_TEXTURE_2D);
-    gl->texCoord2i(gl, sx - dx, sy - dy);
-    gl->recti(gl, dx, dy, dx + w, dy + h);
-    gl->disable(gl, GGL_TEXTURE_2D);
-
-    if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888)
-        gl->enable(gl, GGL_BLEND);
-}
-
-unsigned int gr_get_width(gr_surface surface) {
-    if (surface == NULL) {
-        return 0;
-    }
-    return ((GGLSurface*) surface)->width;
-}
-
-unsigned int gr_get_height(gr_surface surface) {
-    if (surface == NULL) {
-        return 0;
-    }
-    return ((GGLSurface*) surface)->height;
-}
-
-int gr_getMaxFontHeight(void *font)
-{
-    GRFont *fnt = (GRFont*) font;
-
-    if (!fnt)
-        return -1;
-
-    return gr_ttf_getMaxFontHeight(font);
-}
-
-int gr_init(void)
-{
-    gglInit(&gr_context);
-    GGLContext *gl = gr_context;
-
-    gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);
-    if (gr_vt_fd < 0) {
-        // This is non-fatal; post-Cupcake kernels don't have tty0.
-    } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {
-        // However, if we do open tty0, we expect the ioctl to work.
-        perror("failed KDSETMODE to KD_GRAPHICS on tty0");
-        gr_exit();
-        return -1;
-    }
-
-    gr_fb_fd = get_framebuffer(gr_framebuffer);
-    if (gr_fb_fd < 0) {
-        perror("Unable to get framebuffer.\n");
-        gr_exit();
-        return -1;
-    }
-
-    get_memory_surface(&gr_mem_surface);
-
-    fprintf(stderr, "framebuffer: fd %d (%d x %d)\n",
-            gr_fb_fd, gr_framebuffer[0].width, gr_framebuffer[0].height);
-
-    /* start with 0 as front (displayed) and 1 as back (drawing) */
-    gr_active_fb = 0;
-    if (!has_overlay)
-        set_active_framebuffer(0);
-    gl->colorBuffer(gl, &gr_mem_surface);
-
-    gl->activeTexture(gl, 0);
-    gl->enable(gl, GGL_BLEND);
-    gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);
-
-#ifdef TW_SCREEN_BLANK_ON_BOOT
-    printf("TW_SCREEN_BLANK_ON_BOOT := true\n");
-    gr_fb_blank(true);
-    gr_fb_blank(false);
-#endif
-
-    if (!alloc_ion_mem(fi.line_length * vi.yres))
-        allocate_overlay(gr_fb_fd, gr_framebuffer);
-
-    return 0;
-}
-
-void gr_exit(void)
-{
-    free_overlay(gr_fb_fd);
-    free_ion_mem();
-
-    close(gr_fb_fd);
-    gr_fb_fd = -1;
-
-    free(gr_mem_surface.data);
-
-    ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
-    close(gr_vt_fd);
-    gr_vt_fd = -1;
-}
-
-int gr_fb_width(void)
-{
-    return gr_framebuffer[0].width;
-}
-
-int gr_fb_height(void)
-{
-    return gr_framebuffer[0].height;
-}
-
-gr_pixel *gr_fb_data(void)
-{
-    return (unsigned short *) gr_mem_surface.data;
-}
-
-int gr_fb_blank(int blank)
-{
-    int ret;
-    //if (blank)
-        //free_overlay(gr_fb_fd);
-
-    ret = ioctl(gr_fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
-    if (ret < 0)
-        perror("ioctl(): blank");
-
-    //if (!blank)
-        //allocate_overlay(gr_fb_fd, gr_framebuffer);
-    return ret;
-}
-
-int gr_get_surface(gr_surface* surface)
-{
-    GGLSurface* ms = malloc(sizeof(GGLSurface));
-    if (!ms)    return -1;
-
-    // Allocate the data
-    get_memory_surface(ms);
-
-    // Now, copy the data
-    memcpy(ms->data, gr_mem_surface.data, vi.xres * vi.yres * vi.bits_per_pixel / 8);
-
-    *surface = (gr_surface*) ms;
-    return 0;
-}
-
-int gr_free_surface(gr_surface surface)
-{
-    if (!surface)
-        return -1;
-
-    GGLSurface* ms = (GGLSurface*) surface;
-    free(ms->data);
-    free(ms);
-    return 0;
-}
-
-void gr_write_frame_to_file(int fd)
-{
-    write(fd, gr_mem_surface.data, vi.xres * vi.yres * vi.bits_per_pixel / 8);
-}
diff --git a/minuitwrp/graphics.cpp b/minuitwrp/graphics.cpp
new file mode 100644
index 0000000..47325d0
--- /dev/null
+++ b/minuitwrp/graphics.cpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/fb.h>
+#include <linux/kd.h>
+
+#include <time.h>
+
+#include <pixelflinger/pixelflinger.h>
+#include "../gui/placement.h"
+#include "minui.h"
+#include "graphics.h"
+
+struct GRFont {
+    GRSurface* texture;
+    int cwidth;
+    int cheight;
+};
+
+static GRFont* gr_font = NULL;
+static minui_backend* gr_backend = NULL;
+
+static int overscan_percent = OVERSCAN_PERCENT;
+static int overscan_offset_x = 0;
+static int overscan_offset_y = 0;
+
+static unsigned char gr_current_r = 255;
+static unsigned char gr_current_g = 255;
+static unsigned char gr_current_b = 255;
+static unsigned char gr_current_a = 255;
+static unsigned char rgb_555[2];
+static unsigned char gr_current_r5 = 31;
+static unsigned char gr_current_g5 = 63;
+static unsigned char gr_current_b5 = 31;
+
+GRSurface* gr_draw = NULL;
+
+static GGLContext *gr_context = 0;
+GGLSurface gr_mem_surface;
+static int gr_is_curr_clr_opaque = 0;
+
+static bool outside(int x, int y)
+{
+    return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height;
+}
+
+int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale)
+{
+    GGLContext *gl = gr_context;
+    void* vfont = pFont;
+    GRFont *font = (GRFont*) pFont;
+    unsigned off;
+    unsigned cwidth;
+    int y_scale = 0, measured_width, measured_height, ret, new_height;
+
+    if (!s || strlen(s) == 0 || !font)
+        return 0;
+
+    measured_height = gr_ttf_getMaxFontHeight(font);
+
+    if (scale) {
+        measured_width = gr_ttf_measureEx(s, vfont);
+        if (measured_width > max_width) {
+            // Adjust font size down until the text fits
+            void *new_font = gr_ttf_scaleFont(vfont, max_width, measured_width);
+            if (!new_font) {
+                printf("gr_textEx_scaleW new_font is NULL\n");
+                return 0;
+            }
+            measured_width = gr_ttf_measureEx(s, new_font);
+            // These next 2 lines adjust the y point based on the new font's height
+            new_height = gr_ttf_getMaxFontHeight(new_font);
+            y_scale = (measured_height - new_height) / 2;
+            vfont = new_font;
+        }
+    } else
+        measured_width = gr_ttf_measureEx(s, vfont);
+
+    int x_adj = measured_width;
+    if (measured_width > max_width)
+        x_adj = max_width;
+
+    if (placement != TOP_LEFT && placement != BOTTOM_LEFT && placement != TEXT_ONLY_RIGHT) {
+        if (placement == CENTER || placement == CENTER_X_ONLY)
+            x -= (x_adj / 2);
+        else
+            x -= x_adj;
+    }
+
+    if (placement != TOP_LEFT && placement != TOP_RIGHT) {
+        if (placement == CENTER || placement == TEXT_ONLY_RIGHT)
+            y -= (measured_height / 2);
+        else if (placement == BOTTOM_LEFT || placement == BOTTOM_RIGHT)
+            y -= measured_height;
+    }
+    return gr_ttf_textExWH(gl, x, y + y_scale, s, vfont, measured_width + x, -1);
+}
+
+void gr_clip(int x, int y, int w, int h)
+{
+    GGLContext *gl = gr_context;
+    gl->scissor(gl, x, y, w, h);
+    gl->enable(gl, GGL_SCISSOR_TEST);
+}
+
+void gr_noclip()
+{
+    GGLContext *gl = gr_context;
+    gl->scissor(gl, 0, 0, gr_fb_width(), gr_fb_height());
+    gl->disable(gl, GGL_SCISSOR_TEST);
+}
+
+void gr_line(int x0, int y0, int x1, int y1, int width)
+{
+    GGLContext *gl = gr_context;
+
+    if(gr_is_curr_clr_opaque)
+        gl->disable(gl, GGL_BLEND);
+
+    const int coords0[2] = { x0 << 4, y0 << 4 };
+    const int coords1[2] = { x1 << 4, y1 << 4 };
+    gl->linex(gl, coords0, coords1, width << 4);
+
+    if(gr_is_curr_clr_opaque)
+        gl->enable(gl, GGL_BLEND);
+}
+
+gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+    int rx, ry;
+    GGLSurface *surface;
+    const int diameter = radius*2 + 1;
+    const int radius_check = radius*radius + radius*0.8;
+    const uint32_t px = (a << 24) | (b << 16) | (g << 8) | r;
+    uint32_t *data;
+
+    surface = (GGLSurface *)malloc(sizeof(GGLSurface));
+    memset(surface, 0, sizeof(GGLSurface));
+
+    data = (uint32_t *)malloc(diameter * diameter * 4);
+    memset(data, 0, diameter * diameter * 4);
+
+    surface->version = sizeof(surface);
+    surface->width = diameter;
+    surface->height = diameter;
+    surface->stride = diameter;
+    surface->data = (GGLubyte*)data;
+    surface->format = GGL_PIXEL_FORMAT_RGBA_8888;
+
+    for(ry = -radius; ry <= radius; ++ry)
+        for(rx = -radius; rx <= radius; ++rx)
+            if(rx*rx+ry*ry <= radius_check)
+                *(data + diameter*(radius + ry) + (radius+rx)) = px;
+
+    return (gr_surface)surface;
+}
+
+void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
+{
+    GGLContext *gl = gr_context;
+    GGLint color[4];
+#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
+    color[0] = ((b << 8) | r) + 1;
+    color[1] = ((g << 8) | g) + 1;
+    color[2] = ((r << 8) | b) + 1;
+    color[3] = ((a << 8) | a) + 1;
+#else
+    color[0] = ((r << 8) | r) + 1;
+    color[1] = ((g << 8) | g) + 1;
+    color[2] = ((b << 8) | b) + 1;
+    color[3] = ((a << 8) | a) + 1;
+#endif
+    gl->color4xv(gl, color);
+
+    gr_is_curr_clr_opaque = (a == 255);
+}
+
+void gr_clear()
+{
+    if (gr_draw->pixel_bytes == 2) {
+        gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+        return;
+    }
+
+    // This code only works on 32bpp devices
+    if (gr_current_r == gr_current_g && gr_current_r == gr_current_b) {
+        memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes);
+    } else {
+        unsigned char* px = gr_draw->data;
+        for (int y = 0; y < gr_draw->height; ++y) {
+            for (int x = 0; x < gr_draw->width; ++x) {
+                *px++ = gr_current_r;
+                *px++ = gr_current_g;
+                *px++ = gr_current_b;
+                px++;
+            }
+            px += gr_draw->row_bytes - (gr_draw->width * gr_draw->pixel_bytes);
+        }
+    }
+}
+
+void gr_fill(int x, int y, int w, int h)
+{
+    GGLContext *gl = gr_context;
+
+    if(gr_is_curr_clr_opaque)
+        gl->disable(gl, GGL_BLEND);
+
+    gl->recti(gl, x, y, x + w, y + h);
+
+    if(gr_is_curr_clr_opaque)
+        gl->enable(gl, GGL_BLEND);
+}
+
+void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy) {
+    if (gr_context == NULL) {
+        return;
+    }
+
+    GGLContext *gl = gr_context;
+    GGLSurface *surface = (GGLSurface*)source;
+
+    if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888)
+        gl->disable(gl, GGL_BLEND);
+
+    gl->bindTexture(gl, surface);
+    gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
+    gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+    gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
+    gl->enable(gl, GGL_TEXTURE_2D);
+    gl->texCoord2i(gl, sx - dx, sy - dy);
+    gl->recti(gl, dx, dy, dx + w, dy + h);
+    gl->disable(gl, GGL_TEXTURE_2D);
+
+    if(surface->format == GGL_PIXEL_FORMAT_RGBX_8888)
+        gl->enable(gl, GGL_BLEND);
+}
+
+unsigned int gr_get_width(gr_surface surface) {
+    if (surface == NULL) {
+        return 0;
+    }
+    return ((GGLSurface*) surface)->width;
+}
+
+unsigned int gr_get_height(gr_surface surface) {
+    if (surface == NULL) {
+        return 0;
+    }
+    return ((GGLSurface*) surface)->height;
+}
+
+void gr_flip() {
+    gr_draw = gr_backend->flip(gr_backend);
+    // On double buffered back ends, when we flip, we need to tell
+    // pixel flinger to draw to the other buffer
+    gr_mem_surface.data = (GGLubyte*)gr_draw->data;
+    gr_context->colorBuffer(gr_context, &gr_mem_surface);
+}
+
+static void get_memory_surface(GGLSurface* ms) {
+    ms->version = sizeof(*ms);
+    ms->width = gr_draw->width;
+    ms->height = gr_draw->height;
+    ms->stride = gr_draw->row_bytes / gr_draw->pixel_bytes;
+    ms->data = (GGLubyte*)gr_draw->data;
+    ms->format = gr_draw->format;
+}
+
+int gr_init(void)
+{
+    gr_draw = NULL;
+
+    gr_backend = open_overlay();
+    if (gr_backend) {
+        gr_draw = gr_backend->init(gr_backend);
+        if (!gr_draw) {
+            gr_backend->exit(gr_backend);
+        } else
+            printf("Using overlay graphics.\n");
+    }
+
+#ifdef HAS_ADF
+    if (!gr_draw) {
+        gr_backend = open_adf();
+        if (gr_backend) {
+            gr_draw = gr_backend->init(gr_backend);
+            if (!gr_draw) {
+                gr_backend->exit(gr_backend);
+            } else
+                printf("Using adf graphics.\n");
+        }
+    }
+#else
+#ifdef MSM_BSP
+	printf("Skipping adf graphics because TW_TARGET_USES_QCOM_BSP := true\n");
+#else
+    printf("Skipping adf graphics -- not present in build tree\n");
+#endif
+#endif
+
+#ifdef HAS_DRM
+    if (!gr_draw) {
+        gr_backend = open_drm();
+        gr_draw = gr_backend->init(gr_backend);
+        if (gr_draw)
+            printf("Using drm graphics.\n");
+    }
+#else
+    printf("Skipping drm graphics -- not present in build tree\n");
+#endif
+
+    if (!gr_draw) {
+        gr_backend = open_fbdev();
+        gr_draw = gr_backend->init(gr_backend);
+        if (gr_draw == NULL) {
+            return -1;
+        } else
+            printf("Using fbdev graphics.\n");
+    }
+
+    overscan_offset_x = gr_draw->width * overscan_percent / 100;
+    overscan_offset_y = gr_draw->height * overscan_percent / 100;
+
+    // Set up pixelflinger
+    get_memory_surface(&gr_mem_surface);
+    gglInit(&gr_context);
+    GGLContext *gl = gr_context;
+    gl->colorBuffer(gl, &gr_mem_surface);
+
+    gl->activeTexture(gl, 0);
+    gl->enable(gl, GGL_BLEND);
+    gl->blendFunc(gl, GGL_SRC_ALPHA, GGL_ONE_MINUS_SRC_ALPHA);
+
+    gr_flip();
+    gr_flip();
+
+    return 0;
+}
+
+void gr_exit(void)
+{
+    gr_backend->exit(gr_backend);
+}
+
+int gr_fb_width(void)
+{
+    return gr_draw->width - 2*overscan_offset_x;
+}
+
+int gr_fb_height(void)
+{
+    return gr_draw->height - 2*overscan_offset_y;
+}
+
+void gr_fb_blank(bool blank)
+{
+    gr_backend->blank(gr_backend, blank);
+}
+
+int gr_get_surface(gr_surface* surface)
+{
+    GGLSurface* ms = (GGLSurface*)malloc(sizeof(GGLSurface));
+    if (!ms)    return -1;
+
+    // Allocate the data
+    get_memory_surface(ms);
+    ms->data = (GGLubyte*)malloc(ms->stride * ms->height * gr_draw->pixel_bytes);
+
+    // Now, copy the data
+    memcpy(ms->data, gr_mem_surface.data, gr_draw->width * gr_draw->height * gr_draw->pixel_bytes / 8);
+
+    *surface = (gr_surface*) ms;
+    return 0;
+}
+
+int gr_free_surface(gr_surface surface)
+{
+    if (!surface)
+        return -1;
+
+    GGLSurface* ms = (GGLSurface*) surface;
+    free(ms->data);
+    free(ms);
+    return 0;
+}
+
+void gr_write_frame_to_file(int fd)
+{
+    write(fd, gr_mem_surface.data, gr_draw->width * gr_draw->height * gr_draw->pixel_bytes / 8);
+}
diff --git a/minuitwrp/graphics.h b/minuitwrp/graphics.h
new file mode 100644
index 0000000..a4115fd
--- /dev/null
+++ b/minuitwrp/graphics.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 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 _GRAPHICS_H_
+#define _GRAPHICS_H_
+
+#include "minui.h"
+
+// TODO: lose the function pointers.
+struct minui_backend {
+    // Initializes the backend and returns a GRSurface* to draw into.
+    GRSurface* (*init)(minui_backend*);
+
+    // Causes the current drawing surface (returned by the most recent
+    // call to flip() or init()) to be displayed, and returns a new
+    // drawing surface.
+    GRSurface* (*flip)(minui_backend*);
+
+    // Blank (or unblank) the screen.
+    void (*blank)(minui_backend*, bool);
+
+    // Device cleanup when drawing is done.
+    void (*exit)(minui_backend*);
+};
+
+minui_backend* open_fbdev();
+minui_backend* open_adf();
+minui_backend* open_drm();
+minui_backend* open_overlay();
+
+#endif
diff --git a/minuitwrp/graphics_adf.cpp b/minuitwrp/graphics_adf.cpp
new file mode 100644
index 0000000..b71bed2
--- /dev/null
+++ b/minuitwrp/graphics_adf.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+
+#include <adf/adf.h>
+
+#include "graphics.h"
+#include <pixelflinger/pixelflinger.h>
+
+struct adf_surface_pdata {
+    GRSurface base;
+    int fd;
+    __u32 offset;
+    __u32 pitch;
+    unsigned char* adf_data;
+};
+
+struct adf_pdata {
+    minui_backend base;
+    int intf_fd;
+    adf_id_t eng_id;
+    __u32 format;
+
+    unsigned int current_surface;
+    unsigned int n_surfaces;
+    adf_surface_pdata surfaces[2];
+};
+
+static GRSurface* adf_flip(minui_backend *backend);
+static void adf_blank(minui_backend *backend, bool blank);
+
+static int adf_surface_init(adf_pdata *pdata, drm_mode_modeinfo *mode, adf_surface_pdata *surf) {
+    memset(surf, 0, sizeof(*surf));
+
+    surf->fd = adf_interface_simple_buffer_alloc(pdata->intf_fd, mode->hdisplay,
+            mode->vdisplay, pdata->format, &surf->offset, &surf->pitch);
+    if (surf->fd < 0)
+        return surf->fd;
+
+    surf->base.width = mode->hdisplay;
+    surf->base.height = mode->vdisplay;
+    surf->base.row_bytes = surf->pitch;
+    surf->base.pixel_bytes = (pdata->format == DRM_FORMAT_RGB565) ? 2 : 4;
+    if (pdata->format == DRM_FORMAT_ABGR8888)
+        surf->base.format = GGL_PIXEL_FORMAT_BGRA_8888;
+    else if (pdata->format == DRM_FORMAT_BGRA8888)
+        surf->base.format = GGL_PIXEL_FORMAT_BGRA_8888;
+    else if (pdata->format == DRM_FORMAT_RGBA8888)
+        surf->base.format = GGL_PIXEL_FORMAT_RGBA_8888;
+    else if (pdata->format == DRM_FORMAT_RGBX8888)
+        surf->base.format = GGL_PIXEL_FORMAT_RGBX_8888;
+    else
+        surf->base.format = GGL_PIXEL_FORMAT_RGB_565;
+
+    surf->adf_data = reinterpret_cast<uint8_t*>(mmap(NULL,
+                                                      surf->pitch * surf->base.height, PROT_WRITE,
+                                                      MAP_SHARED, surf->fd, surf->offset));
+    if (surf->adf_data == MAP_FAILED) {
+        close(surf->fd);
+        return -errno;
+    }
+
+    return 0;
+}
+
+static int adf_interface_init(adf_pdata *pdata)
+{
+    adf_interface_data intf_data;
+    int ret = 0;
+    int err;
+    unsigned char* framebuffer_data = NULL;
+
+    err = adf_get_interface_data(pdata->intf_fd, &intf_data);
+    if (err < 0)
+        return err;
+
+    err = adf_surface_init(pdata, &intf_data.current_mode, &pdata->surfaces[0]);
+    if (err < 0) {
+        fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err));
+        ret = err;
+        goto done;
+    }
+
+    /* Allocate a single buffer for drawing. graphics.cpp will draw to
+     * this buffer which will later be copied to the mmapped adf buffer.
+     * Using a regular memory buffer improves performance by about 10x. */
+    framebuffer_data = (unsigned char*)calloc(pdata->surfaces[0].pitch * pdata->surfaces[0].base.height, 1);
+    if (framebuffer_data == NULL) {
+        printf("failed to calloc surface data\n");
+        close(pdata->surfaces[0].fd);
+        munmap(pdata->surfaces[0].adf_data, pdata->surfaces[0].pitch * pdata->surfaces[0].base.height);
+        ret = -1;
+        goto done;
+    }
+    pdata->surfaces[0].base.data = framebuffer_data;
+
+    err = adf_surface_init(pdata, &intf_data.current_mode,
+            &pdata->surfaces[1]);
+    if (err < 0) {
+        fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err));
+        memset(&pdata->surfaces[1], 0, sizeof(pdata->surfaces[1]));
+        pdata->n_surfaces = 1;
+    } else {
+        pdata->n_surfaces = 2;
+        pdata->surfaces[1].base.data = framebuffer_data;
+    }
+
+done:
+    adf_free_interface_data(&intf_data);
+    return ret;
+}
+
+static int adf_device_init(adf_pdata *pdata, adf_device *dev)
+{
+    adf_id_t intf_id;
+    int intf_fd;
+    int err;
+
+    err = adf_find_simple_post_configuration(dev, &pdata->format, 1, &intf_id,
+            &pdata->eng_id);
+    if (err < 0)
+        return err;
+
+    err = adf_device_attach(dev, pdata->eng_id, intf_id);
+    if (err < 0 && err != -EALREADY)
+        return err;
+
+    pdata->intf_fd = adf_interface_open(dev, intf_id, O_RDWR);
+    if (pdata->intf_fd < 0)
+        return pdata->intf_fd;
+
+    err = adf_interface_init(pdata);
+    if (err < 0) {
+        close(pdata->intf_fd);
+        pdata->intf_fd = -1;
+    }
+
+    return err;
+}
+
+static GRSurface* adf_init(minui_backend *backend)
+{
+    adf_pdata *pdata = (adf_pdata *)backend;
+    adf_id_t *dev_ids = NULL;
+    ssize_t n_dev_ids, i;
+    GRSurface* ret;
+
+#if defined(RECOVERY_ABGR)
+    pdata->format = DRM_FORMAT_ABGR8888;
+    printf("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
+#elif defined(RECOVERY_BGRA)
+    pdata->format = DRM_FORMAT_BGRA8888;
+    printf("setting DRM_FORMAT_BGRA8888 and GGL_PIXEL_FORMAT_BGRA_8888\n");
+#elif defined(RECOVERY_RGBA)
+    pdata->format = DRM_FORMAT_RGBA8888;
+    printf("setting DRM_FORMAT_RGBA8888 and GGL_PIXEL_FORMAT_RGBA_8888\n");
+#elif defined(RECOVERY_RGBX)
+    pdata->format = DRM_FORMAT_RGBX8888;
+    printf("setting DRM_FORMAT_RGBX8888 and GGL_PIXEL_FORMAT_RGBX_8888\n");
+#else
+    pdata->format = DRM_FORMAT_RGB565;
+    printf("setting DRM_FORMAT_RGB565 and GGL_PIXEL_FORMAT_RGB_565\n");
+#endif
+
+    n_dev_ids = adf_devices(&dev_ids);
+    if (n_dev_ids == 0) {
+        return NULL;
+    } else if (n_dev_ids < 0) {
+        fprintf(stderr, "enumerating adf devices failed: %s\n",
+                strerror(-n_dev_ids));
+        return NULL;
+    }
+
+    pdata->intf_fd = -1;
+
+    for (i = 0; i < n_dev_ids && pdata->intf_fd < 0; i++) {
+        adf_device dev;
+
+        int err = adf_device_open(dev_ids[i], O_RDWR, &dev);
+        if (err < 0) {
+            fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i],
+                    strerror(-err));
+            continue;
+        }
+
+        err = adf_device_init(pdata, &dev);
+        if (err < 0)
+            fprintf(stderr, "initializing adf device %u failed: %s\n",
+                    dev_ids[i], strerror(-err));
+
+        adf_device_close(&dev);
+    }
+
+    free(dev_ids);
+
+    if (pdata->intf_fd < 0)
+        return NULL;
+
+    ret = adf_flip(backend);
+
+    adf_blank(backend, true);
+    adf_blank(backend, false);
+
+    return ret;
+}
+
+static GRSurface* adf_flip(minui_backend *backend)
+{
+    adf_pdata *pdata = (adf_pdata *)backend;
+    adf_surface_pdata *surf = &pdata->surfaces[pdata->current_surface];
+
+    memcpy(surf->adf_data, surf->base.data, surf->pitch * surf->base.height);
+    int fence_fd = adf_interface_simple_post(pdata->intf_fd, pdata->eng_id,
+            surf->base.width, surf->base.height, pdata->format, surf->fd,
+            surf->offset, surf->pitch, -1);
+    if (fence_fd >= 0)
+        close(fence_fd);
+
+    pdata->current_surface = (pdata->current_surface + 1) % pdata->n_surfaces;
+    return &pdata->surfaces[pdata->current_surface].base;
+}
+
+static void adf_blank(minui_backend *backend, bool blank)
+{
+    adf_pdata *pdata = (adf_pdata *)backend;
+    adf_interface_blank(pdata->intf_fd,
+            blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON);
+}
+
+static void adf_surface_destroy(adf_surface_pdata *surf)
+{
+    munmap(surf->adf_data, surf->pitch * surf->base.height);
+    close(surf->fd);
+}
+
+static void adf_exit(minui_backend *backend)
+{
+    adf_pdata *pdata = (adf_pdata *)backend;
+    unsigned int i;
+
+    free(pdata->surfaces[0].base.data);
+    for (i = 0; i < pdata->n_surfaces; i++)
+        adf_surface_destroy(&pdata->surfaces[i]);
+    if (pdata->intf_fd >= 0)
+        close(pdata->intf_fd);
+    free(pdata);
+}
+
+minui_backend *open_adf()
+{
+    adf_pdata* pdata = reinterpret_cast<adf_pdata*>(calloc(1, sizeof(*pdata)));
+    if (!pdata) {
+        perror("allocating adf backend failed");
+        return NULL;
+    }
+
+    pdata->base.init = adf_init;
+    pdata->base.flip = adf_flip;
+    pdata->base.blank = adf_blank;
+    pdata->base.exit = adf_exit;
+    return &pdata->base;
+}
diff --git a/minuitwrp/graphics_drm.cpp b/minuitwrp/graphics_drm.cpp
new file mode 100644
index 0000000..9bbf7e9
--- /dev/null
+++ b/minuitwrp/graphics_drm.cpp
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <drm_fourcc.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "minui.h"
+#include "graphics.h"
+#include <pixelflinger/pixelflinger.h>
+
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A)))
+
+struct drm_surface {
+    GRSurface base;
+    uint32_t fb_id;
+    uint32_t handle;
+};
+
+static drm_surface *drm_surfaces[2];
+static int current_buffer;
+
+static drmModeCrtc *main_monitor_crtc;
+static drmModeConnector *main_monitor_connector;
+
+static int drm_fd = -1;
+
+static void drm_disable_crtc(int drm_fd, drmModeCrtc *crtc) {
+    if (crtc) {
+        drmModeSetCrtc(drm_fd, crtc->crtc_id,
+                       0, // fb_id
+                       0, 0,  // x,y
+                       NULL,  // connectors
+                       0,     // connector_count
+                       NULL); // mode
+    }
+}
+
+static void drm_enable_crtc(int drm_fd, drmModeCrtc *crtc,
+                            struct drm_surface *surface) {
+    int32_t ret;
+
+    ret = drmModeSetCrtc(drm_fd, crtc->crtc_id,
+                         surface->fb_id,
+                         0, 0,  // x,y
+                         &main_monitor_connector->connector_id,
+                         1,  // connector_count
+                         &main_monitor_crtc->mode);
+
+    if (ret)
+        printf("drmModeSetCrtc failed ret=%d\n", ret);
+}
+
+static void drm_blank(minui_backend* backend __unused, bool blank) {
+    if (blank)
+        drm_disable_crtc(drm_fd, main_monitor_crtc);
+    else
+        drm_enable_crtc(drm_fd, main_monitor_crtc,
+                        drm_surfaces[current_buffer]);
+}
+
+static void drm_destroy_surface(struct drm_surface *surface) {
+    struct drm_gem_close gem_close;
+    int ret;
+
+    if(!surface)
+        return;
+
+    if (surface->base.data)
+        munmap(surface->base.data,
+               surface->base.row_bytes * surface->base.height);
+
+    if (surface->fb_id) {
+        ret = drmModeRmFB(drm_fd, surface->fb_id);
+        if (ret)
+            printf("drmModeRmFB failed ret=%d\n", ret);
+    }
+
+    if (surface->handle) {
+        memset(&gem_close, 0, sizeof(gem_close));
+        gem_close.handle = surface->handle;
+
+        ret = drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+        if (ret)
+            printf("DRM_IOCTL_GEM_CLOSE failed ret=%d\n", ret);
+    }
+
+    free(surface);
+}
+
+static int drm_format_to_bpp(uint32_t format) {
+    switch(format) {
+        case DRM_FORMAT_ABGR8888:
+        case DRM_FORMAT_BGRA8888:
+        case DRM_FORMAT_RGBX8888:
+        case DRM_FORMAT_BGRX8888:
+        case DRM_FORMAT_XBGR8888:
+        case DRM_FORMAT_ARGB8888:
+        case DRM_FORMAT_XRGB8888:
+            return 32;
+        case DRM_FORMAT_RGB565:
+            return 16;
+        default:
+            printf("Unknown format %d\n", format);
+            return 32;
+    }
+}
+
+static drm_surface *drm_create_surface(int width, int height) {
+    struct drm_surface *surface;
+    struct drm_mode_create_dumb create_dumb;
+    uint32_t format;
+    __u32 base_format;
+    int ret;
+
+    surface = (struct drm_surface*)calloc(1, sizeof(*surface));
+    if (!surface) {
+        printf("Can't allocate memory\n");
+        return NULL;
+    }
+
+#if defined(RECOVERY_ABGR)
+    format = DRM_FORMAT_RGBA8888;
+    base_format = GGL_PIXEL_FORMAT_RGBA_8888;
+    printf("setting DRM_FORMAT_RGBA8888 and GGL_PIXEL_FORMAT_RGBA_8888\n");
+#elif defined(RECOVERY_BGRA)
+    format = DRM_FORMAT_ARGB8888;
+    base_format = GGL_PIXEL_FORMAT_BGRA_8888;
+    printf("setting DRM_FORMAT_ARGB8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
+#elif defined(RECOVERY_RGBA)
+    format = DRM_FORMAT_ABGR8888;
+    base_format = GGL_PIXEL_FORMAT_BGRA_8888;
+    printf("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
+#elif defined(RECOVERY_RGBX)
+    format = DRM_FORMAT_XBGR8888;
+    base_format = GGL_PIXEL_FORMAT_BGRA_8888;
+    printf("setting DRM_FORMAT_XBGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n");
+#else
+    format = DRM_FORMAT_RGB565;
+    base_format = GGL_PIXEL_FORMAT_BGRA_8888;
+    printf("setting DRM_FORMAT_RGB565 and GGL_PIXEL_FORMAT_RGB_565\n");
+#endif
+
+    memset(&create_dumb, 0, sizeof(create_dumb));
+    create_dumb.height = height;
+    create_dumb.width = width;
+    create_dumb.bpp = drm_format_to_bpp(format);
+    create_dumb.flags = 0;
+
+    ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
+    if (ret) {
+        printf("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n",ret);
+        drm_destroy_surface(surface);
+        return NULL;
+    }
+    surface->handle = create_dumb.handle;
+
+    uint32_t handles[4], pitches[4], offsets[4];
+
+    handles[0] = surface->handle;
+    pitches[0] = create_dumb.pitch;
+    offsets[0] = 0;
+
+    ret = drmModeAddFB2(drm_fd, width, height,
+            format, handles, pitches, offsets,
+            &(surface->fb_id), 0);
+    if (ret) {
+        printf("drmModeAddFB2 failed ret=%d\n", ret);
+        drm_destroy_surface(surface);
+        return NULL;
+    }
+
+    struct drm_mode_map_dumb map_dumb;
+    memset(&map_dumb, 0, sizeof(map_dumb));
+    map_dumb.handle = create_dumb.handle;
+    ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
+    if (ret) {
+        printf("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n",ret);
+        drm_destroy_surface(surface);
+        return NULL;;
+    }
+
+    surface->base.height = height;
+    surface->base.width = width;
+    surface->base.row_bytes = create_dumb.pitch;
+    surface->base.pixel_bytes = create_dumb.bpp / 8;
+    surface->base.format = base_format;
+    surface->base.data = (unsigned char*)
+                         mmap(NULL,
+                              surface->base.height * surface->base.row_bytes,
+                              PROT_READ | PROT_WRITE, MAP_SHARED,
+                              drm_fd, map_dumb.offset);
+    if (surface->base.data == MAP_FAILED) {
+        perror("mmap() failed");
+        drm_destroy_surface(surface);
+        return NULL;
+    }
+
+    return surface;
+}
+
+static drmModeCrtc *find_crtc_for_connector(int fd,
+                            drmModeRes *resources,
+                            drmModeConnector *connector) {
+    int i, j;
+    drmModeEncoder *encoder;
+    int32_t crtc;
+
+    /*
+     * Find the encoder. If we already have one, just use it.
+     */
+    if (connector->encoder_id)
+        encoder = drmModeGetEncoder(fd, connector->encoder_id);
+    else
+        encoder = NULL;
+
+    if (encoder && encoder->crtc_id) {
+        crtc = encoder->crtc_id;
+        drmModeFreeEncoder(encoder);
+        return drmModeGetCrtc(fd, crtc);
+    }
+
+    /*
+     * Didn't find anything, try to find a crtc and encoder combo.
+     */
+    crtc = -1;
+    for (i = 0; i < connector->count_encoders; i++) {
+        encoder = drmModeGetEncoder(fd, connector->encoders[i]);
+
+        if (encoder) {
+            for (j = 0; j < resources->count_crtcs; j++) {
+                if (!(encoder->possible_crtcs & (1 << j)))
+                    continue;
+                crtc = resources->crtcs[j];
+                break;
+            }
+            if (crtc >= 0) {
+                drmModeFreeEncoder(encoder);
+                return drmModeGetCrtc(fd, crtc);
+            }
+        }
+    }
+
+    return NULL;
+}
+
+static drmModeConnector *find_used_connector_by_type(int fd,
+                                 drmModeRes *resources,
+                                 unsigned type) {
+    int i;
+    for (i = 0; i < resources->count_connectors; i++) {
+        drmModeConnector *connector;
+
+        connector = drmModeGetConnector(fd, resources->connectors[i]);
+        if (connector) {
+            if ((connector->connector_type == type) &&
+                    (connector->connection == DRM_MODE_CONNECTED) &&
+                    (connector->count_modes > 0))
+                return connector;
+
+            drmModeFreeConnector(connector);
+        }
+    }
+    return NULL;
+}
+
+static drmModeConnector *find_first_connected_connector(int fd,
+                             drmModeRes *resources) {
+    int i;
+    for (i = 0; i < resources->count_connectors; i++) {
+        drmModeConnector *connector;
+
+        connector = drmModeGetConnector(fd, resources->connectors[i]);
+        if (connector) {
+            if ((connector->count_modes > 0) &&
+                    (connector->connection == DRM_MODE_CONNECTED))
+                return connector;
+
+            drmModeFreeConnector(connector);
+        }
+    }
+    return NULL;
+}
+
+static drmModeConnector *find_main_monitor(int fd, drmModeRes *resources,
+        uint32_t *mode_index) {
+    unsigned i = 0;
+    int modes;
+    /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
+    unsigned kConnectorPriority[] = {
+        DRM_MODE_CONNECTOR_LVDS,
+        DRM_MODE_CONNECTOR_eDP,
+        DRM_MODE_CONNECTOR_DSI,
+    };
+
+    drmModeConnector *main_monitor_connector = NULL;
+    do {
+        main_monitor_connector = find_used_connector_by_type(fd,
+                                         resources,
+                                         kConnectorPriority[i]);
+        i++;
+    } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority));
+
+    /* If we didn't find a connector, grab the first one that is connected. */
+    if (!main_monitor_connector)
+        main_monitor_connector =
+                find_first_connected_connector(fd, resources);
+
+    /* If we still didn't find a connector, give up and return. */
+    if (!main_monitor_connector)
+        return NULL;
+
+    *mode_index = 0;
+    for (modes = 0; modes < main_monitor_connector->count_modes; modes++) {
+        if (main_monitor_connector->modes[modes].type &
+                DRM_MODE_TYPE_PREFERRED) {
+            *mode_index = modes;
+            break;
+        }
+    }
+
+    return main_monitor_connector;
+}
+
+static void disable_non_main_crtcs(int fd,
+                    drmModeRes *resources,
+                    drmModeCrtc* main_crtc) {
+    int i;
+    drmModeCrtc* crtc;
+
+    for (i = 0; i < resources->count_connectors; i++) {
+        drmModeConnector *connector;
+
+        connector = drmModeGetConnector(fd, resources->connectors[i]);
+        crtc = find_crtc_for_connector(fd, resources, connector);
+        if (crtc->crtc_id != main_crtc->crtc_id)
+            drm_disable_crtc(fd, crtc);
+        drmModeFreeCrtc(crtc);
+    }
+}
+
+static GRSurface* drm_init(minui_backend* backend __unused) {
+    drmModeRes *res = NULL;
+    uint32_t selected_mode;
+    char *dev_name;
+    int width, height;
+    int ret, i;
+
+    /* Consider DRM devices in order. */
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+        uint64_t cap = 0;
+
+        ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+        if (ret < 0)
+            continue;
+
+        drm_fd = open(dev_name, O_RDWR, 0);
+        free(dev_name);
+        if (drm_fd < 0)
+            continue;
+
+        /* We need dumb buffers. */
+        ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
+        if (ret || cap == 0) {
+            close(drm_fd);
+            continue;
+        }
+
+        res = drmModeGetResources(drm_fd);
+        if (!res) {
+            close(drm_fd);
+            continue;
+        }
+
+        /* Use this device if it has at least one connected monitor. */
+        if (res->count_crtcs > 0 && res->count_connectors > 0)
+            if (find_first_connected_connector(drm_fd, res))
+                break;
+
+        drmModeFreeResources(res);
+        close(drm_fd);
+        res = NULL;
+    }
+
+    if (drm_fd < 0 || res == NULL) {
+        perror("cannot find/open a drm device");
+        return NULL;
+    }
+
+    main_monitor_connector = find_main_monitor(drm_fd,
+            res, &selected_mode);
+
+    if (!main_monitor_connector) {
+        printf("main_monitor_connector not found\n");
+        drmModeFreeResources(res);
+        close(drm_fd);
+        return NULL;
+    }
+
+    main_monitor_crtc = find_crtc_for_connector(drm_fd, res,
+                                                main_monitor_connector);
+
+    if (!main_monitor_crtc) {
+        printf("main_monitor_crtc not found\n");
+        drmModeFreeResources(res);
+        close(drm_fd);
+        return NULL;
+    }
+
+    disable_non_main_crtcs(drm_fd,
+                           res, main_monitor_crtc);
+
+    main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
+
+    width = main_monitor_crtc->mode.hdisplay;
+    height = main_monitor_crtc->mode.vdisplay;
+
+    drmModeFreeResources(res);
+
+    drm_surfaces[0] = drm_create_surface(width, height);
+    drm_surfaces[1] = drm_create_surface(width, height);
+    if (!drm_surfaces[0] || !drm_surfaces[1]) {
+        drm_destroy_surface(drm_surfaces[0]);
+        drm_destroy_surface(drm_surfaces[1]);
+        drmModeFreeResources(res);
+        close(drm_fd);
+        return NULL;
+    }
+
+    current_buffer = 0;
+
+    drm_enable_crtc(drm_fd, main_monitor_crtc, drm_surfaces[1]);
+
+    return &(drm_surfaces[0]->base);
+}
+
+static GRSurface* drm_flip(minui_backend* backend __unused) {
+    int ret;
+
+    ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id,
+                          drm_surfaces[current_buffer]->fb_id, 0, NULL);
+    if (ret < 0) {
+        printf("drmModePageFlip failed ret=%d\n", ret);
+        return NULL;
+    }
+    current_buffer = 1 - current_buffer;
+    return &(drm_surfaces[current_buffer]->base);
+}
+
+static void drm_exit(minui_backend* backend __unused) {
+    drm_disable_crtc(drm_fd, main_monitor_crtc);
+    drm_destroy_surface(drm_surfaces[0]);
+    drm_destroy_surface(drm_surfaces[1]);
+    drmModeFreeCrtc(main_monitor_crtc);
+    drmModeFreeConnector(main_monitor_connector);
+    close(drm_fd);
+    drm_fd = -1;
+}
+
+static minui_backend drm_backend = {
+    .init = drm_init,
+    .flip = drm_flip,
+    .blank = drm_blank,
+    .exit = drm_exit,
+};
+
+minui_backend* open_drm() {
+    return &drm_backend;
+}
diff --git a/minuitwrp/graphics_fbdev.cpp b/minuitwrp/graphics_fbdev.cpp
new file mode 100644
index 0000000..10ef4fe
--- /dev/null
+++ b/minuitwrp/graphics_fbdev.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/fb.h>
+#include <linux/kd.h>
+
+#include "minui.h"
+#include "graphics.h"
+#include <pixelflinger/pixelflinger.h>
+
+static GRSurface* fbdev_init(minui_backend*);
+static GRSurface* fbdev_flip(minui_backend*);
+static void fbdev_blank(minui_backend*, bool);
+static void fbdev_exit(minui_backend*);
+
+static GRSurface gr_framebuffer[2];
+static bool double_buffered;
+static GRSurface* gr_draw = NULL;
+static int displayed_buffer;
+
+static fb_var_screeninfo vi;
+static int fb_fd = -1;
+static __u32 smem_len;
+
+static minui_backend my_backend = {
+    .init = fbdev_init,
+    .flip = fbdev_flip,
+    .blank = fbdev_blank,
+    .exit = fbdev_exit,
+};
+
+minui_backend* open_fbdev() {
+    return &my_backend;
+}
+
+static void fbdev_blank(minui_backend* backend __unused, bool blank)
+{
+#if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS)
+    int fd;
+    char brightness[4];
+    snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2);
+
+    fd = open(TW_BRIGHTNESS_PATH, O_RDWR);
+    if (fd < 0) {
+        perror("cannot open LCD backlight");
+        return;
+    }
+    write(fd, blank ? "000" : brightness, 3);
+    close(fd);
+#else
+#ifndef TW_NO_SCREEN_BLANK
+    int ret;
+
+    ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
+    if (ret < 0)
+        perror("ioctl(): blank");
+#endif
+#endif
+}
+
+static void set_displayed_framebuffer(unsigned n)
+{
+    if (n > 1 || !double_buffered) return;
+
+    vi.yres_virtual = gr_framebuffer[0].height * 2;
+    vi.yoffset = n * gr_framebuffer[0].height;
+    vi.bits_per_pixel = gr_framebuffer[0].pixel_bytes * 8;
+    if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) {
+        perror("active fb swap failed");
+    }
+    displayed_buffer = n;
+}
+
+static GRSurface* fbdev_init(minui_backend* backend) {
+    int fd = open("/dev/graphics/fb0", O_RDWR);
+    if (fd == -1) {
+        perror("cannot open fb0");
+        return NULL;
+    }
+
+    fb_fix_screeninfo fi;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+        perror("failed to get fb0 info");
+        close(fd);
+        return NULL;
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
+        perror("failed to get fb0 info");
+        close(fd);
+        return NULL;
+    }
+
+    // We print this out for informational purposes only, but
+    // throughout we assume that the framebuffer device uses an RGBX
+    // pixel format.  This is the case for every development device I
+    // have access to.  For some of those devices (eg, hammerhead aka
+    // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a
+    // different format (XBGR) but actually produces the correct
+    // results on the display when you write RGBX.
+    //
+    // If you have a device that actually *needs* another pixel format
+    // (ie, BGRX, or 565), patches welcome...
+
+    printf("fb0 reports (possibly inaccurate):\n"
+           "  vi.bits_per_pixel = %d\n"
+           "  vi.red.offset   = %3d   .length = %3d\n"
+           "  vi.green.offset = %3d   .length = %3d\n"
+           "  vi.blue.offset  = %3d   .length = %3d\n",
+           vi.bits_per_pixel,
+           vi.red.offset, vi.red.length,
+           vi.green.offset, vi.green.length,
+           vi.blue.offset, vi.blue.length);
+
+    void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (bits == MAP_FAILED) {
+        perror("failed to mmap framebuffer");
+        close(fd);
+        return NULL;
+    }
+
+    memset(bits, 0, fi.smem_len);
+
+#ifdef RECOVERY_RGB_565
+    printf("Forcing pixel format: RGB_565\n");
+    vi.blue.offset    = 0;
+    vi.green.offset   = 5;
+    vi.red.offset     = 11;
+    vi.blue.length    = 5;
+    vi.green.length   = 6;
+    vi.red.length     = 5;
+    vi.blue.msb_right = 0;
+    vi.green.msb_right = 0;
+    vi.red.msb_right = 0;
+    vi.transp.offset  = 0;
+    vi.transp.length  = 0;
+    vi.bits_per_pixel = 16;
+#endif
+
+    gr_framebuffer[0].width = vi.xres;
+    gr_framebuffer[0].height = vi.yres;
+    gr_framebuffer[0].row_bytes = fi.line_length;
+    gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8;
+#ifdef RECOVERY_GRAPHICS_USE_LINELENGTH
+    vi.xres_virtual = fi.line_length / gr_framebuffer[0].pixel_bytes;
+#endif
+    gr_framebuffer[0].data = reinterpret_cast<uint8_t*>(bits);
+    if (vi.bits_per_pixel == 16) {
+        printf("setting GGL_PIXEL_FORMAT_RGB_565\n");
+        gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565;
+    } else if (vi.red.offset == 8) {
+        printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n");
+        gr_framebuffer[0].format = GGL_PIXEL_FORMAT_BGRA_8888;
+    } else if (vi.red.offset == 0) {
+        printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n");
+        gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBA_8888;
+    } else if (vi.red.offset == 24) {
+        printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n");
+        gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888;
+    } else {
+        if (vi.red.length == 8) {
+            printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n");
+            gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGBX_8888;
+        } else {
+            printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n");
+            gr_framebuffer[0].format = GGL_PIXEL_FORMAT_RGB_565;
+        }
+    }
+
+    // Drawing directly to the framebuffer takes about 5 times longer.
+    // Instead, we will allocate some memory and draw to that, then
+    // memcpy the data into the framebuffer later.
+    gr_draw = (GRSurface*) malloc(sizeof(GRSurface));
+    if (!gr_draw) {
+        perror("failed to allocate gr_draw");
+        close(fd);
+        munmap(bits, fi.smem_len);
+        return NULL;
+    }
+    memcpy(gr_draw, gr_framebuffer, sizeof(GRSurface));
+    gr_draw->data = (unsigned char*) calloc(gr_draw->height * gr_draw->row_bytes, 1);
+    if (!gr_draw->data) {
+        perror("failed to allocate in-memory surface");
+        close(fd);
+        free(gr_draw);
+        munmap(bits, fi.smem_len);
+        return NULL;
+    }
+
+    /* check if we can use double buffering */
+    if (vi.yres * fi.line_length * 2 <= fi.smem_len) {
+        double_buffered = true;
+        printf("double buffered\n");
+
+        memcpy(gr_framebuffer+1, gr_framebuffer, sizeof(GRSurface));
+        gr_framebuffer[1].data = gr_framebuffer[0].data +
+            gr_framebuffer[0].height * gr_framebuffer[0].row_bytes;
+
+    } else {
+        double_buffered = false;
+        printf("single buffered\n");
+    }
+#if defined(RECOVERY_BGRA)
+    printf("RECOVERY_BGRA\n");
+#endif
+    fb_fd = fd;
+    set_displayed_framebuffer(0);
+
+    printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height);
+
+    fbdev_blank(backend, true);
+    fbdev_blank(backend, false);
+
+    smem_len = fi.smem_len;
+
+    return gr_draw;
+}
+
+static GRSurface* fbdev_flip(minui_backend* backend __unused) {
+    if (double_buffered) {
+#if defined(RECOVERY_BGRA)
+        // In case of BGRA, do some byte swapping
+        unsigned int idx;
+        unsigned char tmp;
+        unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
+        for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
+                idx += 4) {
+            tmp = ucfb_vaddr[idx];
+            ucfb_vaddr[idx    ] = ucfb_vaddr[idx + 2];
+            ucfb_vaddr[idx + 2] = tmp;
+        }
+#endif
+        // Copy from the in-memory surface to the framebuffer.
+        memcpy(gr_framebuffer[1-displayed_buffer].data, gr_draw->data,
+               gr_draw->height * gr_draw->row_bytes);
+        set_displayed_framebuffer(1-displayed_buffer);
+    } else {
+        // Copy from the in-memory surface to the framebuffer.
+        memcpy(gr_framebuffer[0].data, gr_draw->data,
+               gr_draw->height * gr_draw->row_bytes);
+    }
+    return gr_draw;
+}
+
+static void fbdev_exit(minui_backend* backend __unused) {
+    close(fb_fd);
+    fb_fd = -1;
+
+    if (gr_draw) {
+        free(gr_draw->data);
+        free(gr_draw);
+    }
+    gr_draw = NULL;
+    munmap(gr_framebuffer[0].data, smem_len);
+}
diff --git a/minuitwrp/graphics_overlay.c b/minuitwrp/graphics_overlay.c
deleted file mode 100644
index 723ffa2..0000000
--- a/minuitwrp/graphics_overlay.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include <linux/fb.h>
-#include <linux/kd.h>
-
-#ifdef MSM_BSP
-#include <linux/msm_mdp.h>
-#include <linux/msm_ion.h>
-#endif
-
-#include <pixelflinger/pixelflinger.h>
-
-#include "minui.h"
-
-#define MDP_V4_0 400
-
-#ifdef MSM_BSP
-#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
-
-typedef struct {
-    unsigned char *mem_buf;
-    int size;
-    int ion_fd;
-    int mem_fd;
-    struct ion_handle_data handle_data;
-} memInfo;
-
-//Left and right overlay id
-static int overlayL_id = MSMFB_NEW_REQUEST;
-static int overlayR_id = MSMFB_NEW_REQUEST;
-
-static memInfo mem_info;
-
-static int map_mdp_pixel_format()
-{
-    int format = MDP_RGB_565;
-#if defined(RECOVERY_BGRA)
-    format = MDP_BGRA_8888;
-#elif defined(RECOVERY_RGBA)
-    format = MDP_RGBA_8888;
-#elif defined(RECOVERY_RGBX)
-    format = MDP_RGBA_8888;
-#endif
-    return format;
-}
-
-static bool overlay_supported = false;
-static bool isMDP5 = false;
-
-bool target_has_overlay(char *version)
-{
-    int mdp_version;
-
-    if (strlen(version) >= 8) {
-        if(!strncmp(version, "msmfb", strlen("msmfb"))) {
-            char str_ver[4];
-            memcpy(str_ver, version + strlen("msmfb"), 3);
-            str_ver[3] = '\0';
-            mdp_version = atoi(str_ver);
-            if (mdp_version >= MDP_V4_0) {
-                overlay_supported = true;
-            }
-        } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) {
-            overlay_supported = true;
-            isMDP5 = true;
-        }
-    }
-    if (overlay_supported) printf("Using qcomm overlay\n");
-    return overlay_supported;
-}
-
-bool isTargetMdp5()
-{
-    if (isMDP5)
-        return true;
-
-    return false;
-}
-
-int free_ion_mem(void) {
-    if (!overlay_supported)
-        return -EINVAL;
-
-    int ret = 0;
-
-    if (mem_info.mem_buf)
-        munmap(mem_info.mem_buf, mem_info.size);
-
-    if (mem_info.ion_fd >= 0) {
-        ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data);
-        if (ret < 0)
-            perror("free_mem failed ");
-    }
-
-    if (mem_info.mem_fd >= 0)
-        close(mem_info.mem_fd);
-    if (mem_info.ion_fd >= 0)
-        close(mem_info.ion_fd);
-
-    memset(&mem_info, 0, sizeof(mem_info));
-    mem_info.mem_fd = -1;
-    mem_info.ion_fd = -1;
-    return 0;
-}
-
-int alloc_ion_mem(unsigned int size)
-{
-    if (!overlay_supported)
-        return -EINVAL;
-    int result;
-    struct ion_fd_data fd_data;
-    struct ion_allocation_data ionAllocData;
-
-    mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC);
-    if (mem_info.ion_fd < 0) {
-        perror("ERROR: Can't open ion ");
-        return -errno;
-    }
-
-    ionAllocData.flags = 0;
-    ionAllocData.len = size;
-    ionAllocData.align = sysconf(_SC_PAGESIZE);
-#ifdef NEW_ION_HEAP
-    ionAllocData.heap_id_mask =
-#else
-    ionAllocData.heap_mask =
-#endif
-            ION_HEAP(ION_IOMMU_HEAP_ID) |
-            ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID);
-
-    result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC,  &ionAllocData);
-    if(result){
-        perror("ION_IOC_ALLOC Failed ");
-        close(mem_info.ion_fd);
-        return result;
-    }
-
-    fd_data.handle = ionAllocData.handle;
-    mem_info.handle_data.handle = ionAllocData.handle;
-    result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data);
-    if (result) {
-        perror("ION_IOC_MAP Failed ");
-        free_ion_mem();
-        return result;
-    }
-    mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ |
-                PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
-    mem_info.mem_fd = fd_data.fd;
-
-    if (!mem_info.mem_buf) {
-        perror("ERROR: mem_buf MAP_FAILED ");
-        free_ion_mem();
-        return -ENOMEM;
-    }
-
-    return 0;
-}
-
-int allocate_overlay(int fd, GGLSurface gr_fb[])
-{
-    int ret = 0;
-
-    if (!overlay_supported)
-        return -EINVAL;
-
-    if (!isDisplaySplit()) {
-        // Check if overlay is already allocated
-        if (MSMFB_NEW_REQUEST == overlayL_id) {
-            struct mdp_overlay overlayL;
-
-            memset(&overlayL, 0 , sizeof (struct mdp_overlay));
-
-            /* Fill Overlay Data */
-            overlayL.src.width  = ALIGN(gr_fb[0].width, 32);
-            overlayL.src.height = gr_fb[0].height;
-            overlayL.src.format = map_mdp_pixel_format();
-            overlayL.src_rect.w = gr_fb[0].width;
-            overlayL.src_rect.h = gr_fb[0].height;
-            overlayL.dst_rect.w = gr_fb[0].width;
-            overlayL.dst_rect.h = gr_fb[0].height;
-            overlayL.alpha = 0xFF;
-            overlayL.transp_mask = MDP_TRANSP_NOP;
-            overlayL.id = MSMFB_NEW_REQUEST;
-            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
-            if (ret < 0) {
-                perror("Overlay Set Failed");
-                return ret;
-            }
-            overlayL_id = overlayL.id;
-        }
-    } else {
-        float xres = getFbXres();
-        int lSplit = getLeftSplit();
-        float lSplitRatio = lSplit / xres;
-        float lCropWidth = gr_fb[0].width * lSplitRatio;
-        int lWidth = lSplit;
-        int rWidth = gr_fb[0].width - lSplit;
-        int height = gr_fb[0].height;
-
-        if (MSMFB_NEW_REQUEST == overlayL_id) {
-
-            struct mdp_overlay overlayL;
-
-            memset(&overlayL, 0 , sizeof (struct mdp_overlay));
-
-            /* Fill OverlayL Data */
-            overlayL.src.width  = ALIGN(gr_fb[0].width, 32);
-            overlayL.src.height = gr_fb[0].height;
-            overlayL.src.format = map_mdp_pixel_format();
-            overlayL.src_rect.x = 0;
-            overlayL.src_rect.y = 0;
-            overlayL.src_rect.w = lCropWidth;
-            overlayL.src_rect.h = gr_fb[0].height;
-            overlayL.dst_rect.x = 0;
-            overlayL.dst_rect.y = 0;
-            overlayL.dst_rect.w = lWidth;
-            overlayL.dst_rect.h = height;
-            overlayL.alpha = 0xFF;
-            overlayL.transp_mask = MDP_TRANSP_NOP;
-            overlayL.id = MSMFB_NEW_REQUEST;
-            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
-            if (ret < 0) {
-                perror("OverlayL Set Failed");
-                return ret;
-            }
-            overlayL_id = overlayL.id;
-        }
-        if (MSMFB_NEW_REQUEST == overlayR_id) {
-            struct mdp_overlay overlayR;
-
-            memset(&overlayR, 0 , sizeof (struct mdp_overlay));
-
-            /* Fill OverlayR Data */
-            overlayR.src.width  = ALIGN(gr_fb[0].width, 32);
-            overlayR.src.height = gr_fb[0].height;
-            overlayR.src.format = map_mdp_pixel_format();
-            overlayR.src_rect.x = lCropWidth;
-            overlayR.src_rect.y = 0;
-            overlayR.src_rect.w = gr_fb[0].width - lCropWidth;
-            overlayR.src_rect.h = gr_fb[0].height;
-            overlayR.dst_rect.x = 0;
-            overlayR.dst_rect.y = 0;
-            overlayR.dst_rect.w = rWidth;
-            overlayR.dst_rect.h = height;
-            overlayR.alpha = 0xFF;
-            overlayR.flags = MDSS_MDP_RIGHT_MIXER;
-            overlayR.transp_mask = MDP_TRANSP_NOP;
-            overlayR.id = MSMFB_NEW_REQUEST;
-            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR);
-            if (ret < 0) {
-                perror("OverlayR Set Failed");
-                return ret;
-            }
-            overlayR_id = overlayR.id;
-        }
-
-    }
-    return 0;
-}
-
-int free_overlay(int fd)
-{
-    if (!overlay_supported)
-        return -EINVAL;
-
-    int ret = 0;
-    struct mdp_display_commit ext_commit;
-
-    if (!isDisplaySplit()) {
-        if (overlayL_id != MSMFB_NEW_REQUEST) {
-            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
-            if (ret) {
-                perror("Overlay Unset Failed");
-                overlayL_id = MSMFB_NEW_REQUEST;
-                return ret;
-            }
-        }
-    } else {
-
-        if (overlayL_id != MSMFB_NEW_REQUEST) {
-            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
-            if (ret) {
-                perror("OverlayL Unset Failed");
-                overlayL_id = MSMFB_NEW_REQUEST;
-                return ret;
-            }
-        }
-
-        if (overlayR_id != MSMFB_NEW_REQUEST) {
-            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id);
-            if (ret) {
-                perror("OverlayR Unset Failed");
-                overlayR_id = MSMFB_NEW_REQUEST;
-                return ret;
-            }
-        }
-    }
-    memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
-    ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
-    ext_commit.wait_for_finish = 1;
-    ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
-    if (ret < 0) {
-        perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!");
-        overlayL_id = MSMFB_NEW_REQUEST;
-        overlayR_id = MSMFB_NEW_REQUEST;
-        return ret;
-    }
-    overlayL_id = MSMFB_NEW_REQUEST;
-    overlayR_id = MSMFB_NEW_REQUEST;
-
-    return 0;
-}
-
-int overlay_display_frame(int fd, GGLubyte* data, size_t size)
-{
-    if (!overlay_supported)
-        return -EINVAL;
-
-    int ret = 0;
-    struct msmfb_overlay_data ovdataL, ovdataR;
-    struct mdp_display_commit ext_commit;
-
-    if (!isDisplaySplit()) {
-        if (overlayL_id == MSMFB_NEW_REQUEST) {
-            perror("display_frame failed, no overlay\n");
-            return -EINVAL;
-        }
-
-        memcpy(mem_info.mem_buf, data, size);
-
-        memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
-
-        ovdataL.id = overlayL_id;
-        ovdataL.data.flags = 0;
-        ovdataL.data.offset = 0;
-        ovdataL.data.memory_id = mem_info.mem_fd;
-        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
-        if (ret < 0) {
-            perror("overlay_display_frame failed, overlay play Failed\n");
-            return ret;
-        }
-    } else {
-
-        if (overlayL_id == MSMFB_NEW_REQUEST) {
-            perror("display_frame failed, no overlayL \n");
-            return -EINVAL;
-        }
-
-        memcpy(mem_info.mem_buf, data, size);
-
-        memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
-
-        ovdataL.id = overlayL_id;
-        ovdataL.data.flags = 0;
-        ovdataL.data.offset = 0;
-        ovdataL.data.memory_id = mem_info.mem_fd;
-        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
-        if (ret < 0) {
-            perror("overlay_display_frame failed, overlayL play Failed\n");
-            return ret;
-        }
-
-        if (overlayR_id == MSMFB_NEW_REQUEST) {
-            perror("display_frame failed, no overlayR \n");
-            return -EINVAL;
-        }
-        memset(&ovdataR, 0, sizeof(struct msmfb_overlay_data));
-
-        ovdataR.id = overlayR_id;
-        ovdataR.data.flags = 0;
-        ovdataR.data.offset = 0;
-        ovdataR.data.memory_id = mem_info.mem_fd;
-        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataR);
-        if (ret < 0) {
-            perror("overlay_display_frame failed, overlayR play Failed\n");
-            return ret;
-        }
-    }
-    memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
-    ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
-    ext_commit.wait_for_finish = 1;
-    ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
-    if (ret < 0) {
-        perror("overlay_display_frame failed, overlay commit Failed\n!");
-    }
-
-    return ret;
-}
-
-#else
-
-bool target_has_overlay(char *version) {
-    return false;
-}
-
-bool isTargetMdp5() {
-    return false;
-}
-
-int free_ion_mem(void) {
-    return -EINVAL;
-}
-
-int alloc_ion_mem(unsigned int size)
-{
-    return -EINVAL;
-}
-
-int allocate_overlay(int fd, GGLSurface gr_fb[])
-{
-    return -EINVAL;
-}
-
-int free_overlay(int fd)
-{
-    return -EINVAL;
-}
-
-int overlay_display_frame(int fd, GGLubyte* data, size_t size)
-{
-    return -EINVAL;
-}
-
-#endif //#ifdef MSM_BSP
diff --git a/minuitwrp/graphics_overlay.cpp b/minuitwrp/graphics_overlay.cpp
new file mode 100644
index 0000000..5445b6f
--- /dev/null
+++ b/minuitwrp/graphics_overlay.cpp
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/fb.h>
+#include <linux/kd.h>
+
+#ifdef MSM_BSP
+#include <linux/msm_mdp.h>
+#include <linux/msm_ion.h>
+#endif
+
+#include "minui.h"
+#include "graphics.h"
+#include <pixelflinger/pixelflinger.h>
+
+#define MDP_V4_0 400
+#define MAX_DISPLAY_DIM  2048
+
+static GRSurface* overlay_init(minui_backend*);
+static GRSurface* overlay_flip(minui_backend*);
+static void overlay_blank(minui_backend*, bool);
+static void overlay_exit(minui_backend*);
+
+static GRSurface gr_framebuffer;
+static GRSurface* gr_draw = NULL;
+static int displayed_buffer;
+
+static fb_var_screeninfo vi;
+static int fb_fd = -1;
+static bool isMDP5 = false;
+static int leftSplit = 0;
+static int rightSplit = 0;
+#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
+
+static size_t frame_size = 0;
+
+#ifdef MSM_BSP
+typedef struct {
+    unsigned char *mem_buf;
+    int size;
+    int ion_fd;
+    int mem_fd;
+    struct ion_handle_data handle_data;
+} memInfo;
+
+//Left and right overlay id
+static int overlayL_id = MSMFB_NEW_REQUEST;
+static int overlayR_id = MSMFB_NEW_REQUEST;
+
+static memInfo mem_info;
+
+static int map_mdp_pixel_format()
+{
+    if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGB_565)
+        return MDP_RGB_565;
+    else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_BGRA_8888)
+        return MDP_BGRA_8888;
+    else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBA_8888)
+        return MDP_RGBA_8888;
+    else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBX_8888)
+        return MDP_RGBA_8888;
+    printf("No known pixel format for map_mdp_pixel_format, defaulting to MDP_RGB_565.\n");
+    return MDP_RGB_565;
+}
+#endif // MSM_BSP
+
+static minui_backend my_backend = {
+    .init = overlay_init,
+    .flip = overlay_flip,
+    .blank = overlay_blank,
+    .exit = overlay_exit,
+};
+
+bool target_has_overlay(char *version)
+{
+    int ret;
+    int mdp_version;
+    bool overlay_supported = false;
+
+    if (strlen(version) >= 8) {
+        if(!strncmp(version, "msmfb", strlen("msmfb"))) {
+            char str_ver[4];
+            memcpy(str_ver, version + strlen("msmfb"), 3);
+            str_ver[3] = '\0';
+            mdp_version = atoi(str_ver);
+            if (mdp_version >= MDP_V4_0) {
+                overlay_supported = true;
+            }
+        } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) {
+            overlay_supported = true;
+            isMDP5 = true;
+        }
+    }
+
+    return overlay_supported;
+}
+
+minui_backend* open_overlay() {
+    fb_fix_screeninfo fi;
+    int fd;
+
+    fd = open("/dev/graphics/fb0", O_RDWR);
+    if (fd < 0) {
+        perror("open_overlay cannot open fb0");
+        return NULL;
+    }
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+        perror("failed to get fb0 info");
+        close(fd);
+        return NULL;
+    }
+
+    if (target_has_overlay(fi.id)) {
+#ifdef MSM_BSP
+        close(fd);
+        return &my_backend;
+#else
+        printf("Overlay graphics may work (%s), but not enabled. Use TW_TARGET_USES_QCOM_BSP := true to enable.\n", fi.id);
+#endif
+    }
+    close(fd);
+    return NULL;
+}
+
+static void overlay_blank(minui_backend* backend __unused, bool blank)
+{
+#if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS)
+    int fd;
+    char brightness[4];
+    snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2);
+
+    fd = open(TW_BRIGHTNESS_PATH, O_RDWR);
+    if (fd < 0) {
+        perror("cannot open LCD backlight");
+        return;
+    }
+    write(fd, blank ? "000" : brightness, 3);
+    close(fd);
+#else
+    int ret;
+
+    ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
+    if (ret < 0)
+        perror("ioctl(): blank");
+#endif
+}
+
+#ifdef MSM_BSP
+void setDisplaySplit(void) {
+    char split[64] = {0};
+    if (!isMDP5)
+        return;
+    FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
+    if (fp) {
+        //Format "left right" space as delimiter
+        if(fread(split, sizeof(char), 64, fp)) {
+            leftSplit = atoi(split);
+            printf("Left Split=%d\n",leftSplit);
+            char *rght = strpbrk(split, " ");
+            if (rght)
+                rightSplit = atoi(rght + 1);
+            printf("Right Split=%d\n", rightSplit);
+        }
+    } else {
+        printf("Failed to open mdss_fb_split node\n");
+    }
+    if (fp)
+        fclose(fp);
+}
+
+int getLeftSplit(void) {
+   //Default even split for all displays with high res
+   int lSplit = vi.xres / 2;
+
+   //Override if split published by driver
+   if (leftSplit)
+       lSplit = leftSplit;
+
+   return lSplit;
+}
+
+int getRightSplit(void) {
+   return rightSplit;
+}
+
+int free_ion_mem(void) {
+    int ret = 0;
+
+    if (mem_info.mem_buf)
+        munmap(mem_info.mem_buf, mem_info.size);
+
+    if (mem_info.ion_fd >= 0) {
+        ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data);
+        if (ret < 0)
+            perror("free_mem failed ");
+    }
+
+    if (mem_info.mem_fd >= 0)
+        close(mem_info.mem_fd);
+    if (mem_info.ion_fd >= 0)
+        close(mem_info.ion_fd);
+
+    memset(&mem_info, 0, sizeof(mem_info));
+    mem_info.mem_fd = -1;
+    mem_info.ion_fd = -1;
+    return 0;
+}
+
+int alloc_ion_mem(unsigned int size)
+{
+    int result;
+    struct ion_fd_data fd_data;
+    struct ion_allocation_data ionAllocData;
+
+    mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC);
+    if (mem_info.ion_fd < 0) {
+        perror("ERROR: Can't open ion ");
+        return -errno;
+    }
+
+    ionAllocData.flags = 0;
+    ionAllocData.len = size;
+    ionAllocData.align = sysconf(_SC_PAGESIZE);
+#ifdef NEW_ION_HEAP
+    ionAllocData.heap_id_mask =
+#else
+    ionAllocData.heap_mask =
+#endif
+            ION_HEAP(ION_IOMMU_HEAP_ID) |
+            ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID);
+
+    result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC,  &ionAllocData);
+    if(result){
+        perror("ION_IOC_ALLOC Failed ");
+        close(mem_info.ion_fd);
+        return result;
+    }
+
+    fd_data.handle = ionAllocData.handle;
+    mem_info.handle_data.handle = ionAllocData.handle;
+    result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data);
+    if (result) {
+        perror("ION_IOC_MAP Failed ");
+        free_ion_mem();
+        return result;
+    }
+    mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ |
+                PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
+    mem_info.mem_fd = fd_data.fd;
+
+    if (!mem_info.mem_buf) {
+        perror("ERROR: mem_buf MAP_FAILED ");
+        free_ion_mem();
+        return -ENOMEM;
+    }
+
+    return 0;
+}
+
+bool isDisplaySplit(void) {
+    if (vi.xres > MAX_DISPLAY_DIM)
+        return true;
+    //check if right split is set by driver
+    if (getRightSplit())
+        return true;
+
+    return false;
+}
+
+int allocate_overlay(int fd, GRSurface gr_fb)
+{
+    int ret = 0;
+
+    if (!isDisplaySplit()) {
+        // Check if overlay is already allocated
+        if (MSMFB_NEW_REQUEST == overlayL_id) {
+            struct mdp_overlay overlayL;
+
+            memset(&overlayL, 0 , sizeof (struct mdp_overlay));
+
+            /* Fill Overlay Data */
+            overlayL.src.width  = ALIGN(gr_fb.width, 32);
+            overlayL.src.height = gr_fb.height;
+            overlayL.src.format = map_mdp_pixel_format();
+            overlayL.src_rect.w = gr_fb.width;
+            overlayL.src_rect.h = gr_fb.height;
+            overlayL.dst_rect.w = gr_fb.width;
+            overlayL.dst_rect.h = gr_fb.height;
+            overlayL.alpha = 0xFF;
+            overlayL.transp_mask = MDP_TRANSP_NOP;
+            overlayL.id = MSMFB_NEW_REQUEST;
+            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
+            if (ret < 0) {
+                perror("Overlay Set Failed");
+                return ret;
+            }
+            overlayL_id = overlayL.id;
+        }
+    } else {
+        float xres = vi.xres;
+        int lSplit = getLeftSplit();
+        float lSplitRatio = lSplit / xres;
+        float lCropWidth = gr_fb.width * lSplitRatio;
+        int lWidth = lSplit;
+        int rWidth = gr_fb.width - lSplit;
+        int height = gr_fb.height;
+
+        if (MSMFB_NEW_REQUEST == overlayL_id) {
+
+            struct mdp_overlay overlayL;
+
+            memset(&overlayL, 0 , sizeof (struct mdp_overlay));
+
+            /* Fill OverlayL Data */
+            overlayL.src.width  = ALIGN(gr_fb.width, 32);
+            overlayL.src.height = gr_fb.height;
+            overlayL.src.format = map_mdp_pixel_format();
+            overlayL.src_rect.x = 0;
+            overlayL.src_rect.y = 0;
+            overlayL.src_rect.w = lCropWidth;
+            overlayL.src_rect.h = gr_fb.height;
+            overlayL.dst_rect.x = 0;
+            overlayL.dst_rect.y = 0;
+            overlayL.dst_rect.w = lWidth;
+            overlayL.dst_rect.h = height;
+            overlayL.alpha = 0xFF;
+            overlayL.transp_mask = MDP_TRANSP_NOP;
+            overlayL.id = MSMFB_NEW_REQUEST;
+            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
+            if (ret < 0) {
+                perror("OverlayL Set Failed");
+                return ret;
+            }
+            overlayL_id = overlayL.id;
+        }
+        if (MSMFB_NEW_REQUEST == overlayR_id) {
+            struct mdp_overlay overlayR;
+
+            memset(&overlayR, 0 , sizeof (struct mdp_overlay));
+
+            /* Fill OverlayR Data */
+            overlayR.src.width  = ALIGN(gr_fb.width, 32);
+            overlayR.src.height = gr_fb.height;
+            overlayR.src.format = map_mdp_pixel_format();
+            overlayR.src_rect.x = lCropWidth;
+            overlayR.src_rect.y = 0;
+            overlayR.src_rect.w = gr_fb.width - lCropWidth;
+            overlayR.src_rect.h = gr_fb.height;
+            overlayR.dst_rect.x = 0;
+            overlayR.dst_rect.y = 0;
+            overlayR.dst_rect.w = rWidth;
+            overlayR.dst_rect.h = height;
+            overlayR.alpha = 0xFF;
+            overlayR.flags = MDSS_MDP_RIGHT_MIXER;
+            overlayR.transp_mask = MDP_TRANSP_NOP;
+            overlayR.id = MSMFB_NEW_REQUEST;
+            ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR);
+            if (ret < 0) {
+                perror("OverlayR Set Failed");
+                return ret;
+            }
+            overlayR_id = overlayR.id;
+        }
+
+    }
+    return 0;
+}
+
+int overlay_display_frame(int fd, void* data, size_t size)
+{
+    int ret = 0;
+    struct msmfb_overlay_data ovdataL, ovdataR;
+    struct mdp_display_commit ext_commit;
+
+    if (!isDisplaySplit()) {
+        if (overlayL_id == MSMFB_NEW_REQUEST) {
+            perror("display_frame failed, no overlay\n");
+            return -EINVAL;
+        }
+
+        memcpy(mem_info.mem_buf, data, size);
+
+        memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
+
+        ovdataL.id = overlayL_id;
+        ovdataL.data.flags = 0;
+        ovdataL.data.offset = 0;
+        ovdataL.data.memory_id = mem_info.mem_fd;
+        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
+        if (ret < 0) {
+            perror("overlay_display_frame failed, overlay play Failed\n");
+            printf("%i, %i, %i, %i\n", ret, fb_fd, fd, errno);
+            return ret;
+        }
+    } else {
+
+        if (overlayL_id == MSMFB_NEW_REQUEST) {
+            perror("display_frame failed, no overlayL \n");
+            return -EINVAL;
+        }
+
+        memcpy(mem_info.mem_buf, data, size);
+
+        memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
+
+        ovdataL.id = overlayL_id;
+        ovdataL.data.flags = 0;
+        ovdataL.data.offset = 0;
+        ovdataL.data.memory_id = mem_info.mem_fd;
+        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
+        if (ret < 0) {
+            perror("overlay_display_frame failed, overlayL play Failed\n");
+            return ret;
+        }
+
+        if (overlayR_id == MSMFB_NEW_REQUEST) {
+            perror("display_frame failed, no overlayR \n");
+            return -EINVAL;
+        }
+        memset(&ovdataR, 0, sizeof(struct msmfb_overlay_data));
+
+        ovdataR.id = overlayR_id;
+        ovdataR.data.flags = 0;
+        ovdataR.data.offset = 0;
+        ovdataR.data.memory_id = mem_info.mem_fd;
+        ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataR);
+        if (ret < 0) {
+            perror("overlay_display_frame failed, overlayR play Failed\n");
+            return ret;
+        }
+    }
+    memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
+    ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
+    ext_commit.wait_for_finish = 1;
+    ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
+    if (ret < 0) {
+        perror("overlay_display_frame failed, overlay commit Failed\n!");
+    }
+
+    return ret;
+}
+
+static GRSurface* overlay_flip(minui_backend* backend __unused) {
+#if defined(RECOVERY_BGRA)
+    // In case of BGRA, do some byte swapping
+    unsigned int idx;
+    unsigned char tmp;
+    unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
+    for (idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
+            idx += 4) {
+        tmp = ucfb_vaddr[idx];
+        ucfb_vaddr[idx    ] = ucfb_vaddr[idx + 2];
+        ucfb_vaddr[idx + 2] = tmp;
+    }
+#endif
+    // Copy from the in-memory surface to the framebuffer.
+    overlay_display_frame(fb_fd, gr_draw->data, frame_size);
+    return gr_draw;
+}
+
+int free_overlay(int fd)
+{
+    int ret = 0;
+    struct mdp_display_commit ext_commit;
+
+    if (!isDisplaySplit()) {
+        if (overlayL_id != MSMFB_NEW_REQUEST) {
+            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
+            if (ret) {
+                perror("Overlay Unset Failed");
+                overlayL_id = MSMFB_NEW_REQUEST;
+                return ret;
+            }
+        }
+    } else {
+
+        if (overlayL_id != MSMFB_NEW_REQUEST) {
+            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
+            if (ret) {
+                perror("OverlayL Unset Failed");
+            }
+        }
+
+        if (overlayR_id != MSMFB_NEW_REQUEST) {
+            ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id);
+            if (ret) {
+                perror("OverlayR Unset Failed");
+                overlayR_id = MSMFB_NEW_REQUEST;
+                return ret;
+            }
+        }
+    }
+    memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
+    ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
+    ext_commit.wait_for_finish = 1;
+    ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
+    if (ret < 0) {
+        perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!");
+        overlayL_id = MSMFB_NEW_REQUEST;
+        overlayR_id = MSMFB_NEW_REQUEST;
+        return ret;
+    }
+    overlayL_id = MSMFB_NEW_REQUEST;
+    overlayR_id = MSMFB_NEW_REQUEST;
+
+    return 0;
+}
+
+static GRSurface* overlay_init(minui_backend* backend) {
+    int fd = open("/dev/graphics/fb0", O_RDWR);
+    if (fd == -1) {
+        perror("cannot open fb0");
+        return NULL;
+    }
+
+    fb_fix_screeninfo fi;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
+        perror("failed to get fb0 info");
+        close(fd);
+        return NULL;
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
+        perror("failed to get fb0 info");
+        close(fd);
+        return NULL;
+    }
+
+    // We print this out for informational purposes only, but
+    // throughout we assume that the framebuffer device uses an RGBX
+    // pixel format.  This is the case for every development device I
+    // have access to.  For some of those devices (eg, hammerhead aka
+    // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a
+    // different format (XBGR) but actually produces the correct
+    // results on the display when you write RGBX.
+    //
+    // If you have a device that actually *needs* another pixel format
+    // (ie, BGRX, or 565), patches welcome...
+
+    printf("fb0 reports (possibly inaccurate):\n"
+           "  vi.bits_per_pixel = %d\n"
+           "  vi.red.offset   = %3d   .length = %3d\n"
+           "  vi.green.offset = %3d   .length = %3d\n"
+           "  vi.blue.offset  = %3d   .length = %3d\n",
+           vi.bits_per_pixel,
+           vi.red.offset, vi.red.length,
+           vi.green.offset, vi.green.length,
+           vi.blue.offset, vi.blue.length);
+
+    gr_framebuffer.width = vi.xres;
+    gr_framebuffer.height = vi.yres;
+    gr_framebuffer.row_bytes = fi.line_length;
+    gr_framebuffer.pixel_bytes = vi.bits_per_pixel / 8;
+    //gr_framebuffer.data = reinterpret_cast<uint8_t*>(bits);
+    if (vi.bits_per_pixel == 16) {
+        printf("setting GGL_PIXEL_FORMAT_RGB_565\n");
+        gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565;
+    } else if (vi.red.offset == 8) {
+        printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n");
+        gr_framebuffer.format = GGL_PIXEL_FORMAT_BGRA_8888;
+    } else if (vi.red.offset == 0) {
+        printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n");
+        gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBA_8888;
+    } else if (vi.red.offset == 24) {
+        printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n");
+        gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888;
+    } else {
+        if (vi.red.length == 8) {
+            printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n");
+            gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888;
+        } else {
+            printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n");
+            gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565;
+        }
+    }
+
+    frame_size = fi.line_length * vi.yres;
+
+    gr_framebuffer.data = reinterpret_cast<uint8_t*>(calloc(frame_size, 1));
+    if (gr_framebuffer.data == NULL) {
+        perror("failed to calloc framebuffer");
+        close(fd);
+        return NULL;
+    }
+
+    gr_draw = &gr_framebuffer;
+    fb_fd = fd;
+
+    printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height);
+
+    overlay_blank(backend, true);
+    overlay_blank(backend, false);
+
+    if (!alloc_ion_mem(frame_size))
+        allocate_overlay(fb_fd, gr_framebuffer);
+
+    return gr_draw;
+}
+
+static void overlay_exit(minui_backend* backend __unused) {
+    free_overlay(fb_fd);
+    free_ion_mem();
+
+    close(fb_fd);
+    fb_fd = -1;
+
+    if (gr_draw) {
+        free(gr_draw->data);
+        free(gr_draw);
+    }
+    gr_draw = NULL;
+}
+#else // MSM_BSP
+static GRSurface* overlay_flip(minui_backend* backend __unused) {
+    return NULL;
+}
+
+static GRSurface* overlay_init(minui_backend* backend __unused) {
+    return NULL;
+}
+
+static void overlay_exit(minui_backend* backend __unused) {
+    return;
+}
+#endif // MSM_BSP
diff --git a/minuitwrp/graphics_utils.c b/minuitwrp/graphics_utils.cpp
similarity index 91%
rename from minuitwrp/graphics_utils.c
rename to minuitwrp/graphics_utils.cpp
index ea1182d..6ce5704 100644
--- a/minuitwrp/graphics_utils.c
+++ b/minuitwrp/graphics_utils.cpp
@@ -23,7 +23,8 @@
 #include "minui.h"
 
 struct fb_var_screeninfo vi;
-GGLSurface gr_mem_surface;
+extern GGLSurface gr_mem_surface;
+extern GRSurface* gr_draw;
 
 int gr_save_screenshot(const char *dest)
 {
@@ -41,7 +42,11 @@
     if(!fp)
         goto exit;
 
-    img_data = malloc(gr_mem_surface.stride * vi.yres * 4);
+    img_data = (uint8_t *)malloc(gr_mem_surface.stride * gr_mem_surface.height * gr_draw->pixel_bytes);
+    if (!img_data) {
+        printf("gr_save_screenshot failed to malloc img_data\n");
+        goto exit;
+    }
     surface.version = sizeof(surface);
     surface.width = gr_mem_surface.width;
     surface.height = gr_mem_surface.height;
diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h
index 25a785a..018f327 100644
--- a/minuitwrp/minui.h
+++ b/minuitwrp/minui.h
@@ -18,6 +18,16 @@
 #define _MINUI_H_
 
 #include "../gui/placement.h"
+#include <stdbool.h>
+
+struct GRSurface {
+    int width;
+    int height;
+    int row_bytes;
+    int pixel_bytes;
+    unsigned char* data;
+    __u32 format;
+};
 
 typedef void* gr_surface;
 typedef unsigned short gr_pixel;
@@ -32,7 +42,7 @@
 int gr_fb_height(void);
 gr_pixel *gr_fb_data(void);
 void gr_flip(void);
-int gr_fb_blank(int blank);
+void gr_fb_blank(bool blank);
 
 void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
 void gr_clip(int x, int y, int w, int h);
@@ -41,14 +51,7 @@
 void gr_line(int x0, int y0, int x1, int y1, int width);
 gr_surface gr_render_circle(int radius, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
 
-int gr_textEx(int x, int y, const char *s, void* font);
 int gr_textEx_scaleW(int x, int y, const char *s, void* pFont, int max_width, int placement, int scale);
-int gr_textExW(int x, int y, const char *s, void* font, int max_width);
-int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max_height);
-static inline int gr_text(int x, int y, const char *s)     { return gr_textEx(x, y, s, NULL); }
-int gr_measureEx(const char *s, void* font);
-static inline int gr_measure(const char *s)                { return gr_measureEx(s, NULL); }
-int gr_maxExW(const char *s, void* font, int max_width);
 
 int gr_getMaxFontHeight(void *font);
 
@@ -86,11 +89,6 @@
 void res_free_surface(gr_surface surface);
 int res_scale_surface(gr_surface source, gr_surface* destination, float scale_w, float scale_h);
 
-// Needed for AOSP:
-int ev_wait(int timeout);
-void ev_dispatch(void);
-int ev_get_input(int fd, short revents, struct input_event *ev);
-
 int vibrate(int timeout_ms);
 
 #endif
diff --git a/minuitwrp/resources.c b/minuitwrp/resources.cpp
similarity index 88%
rename from minuitwrp/resources.c
rename to minuitwrp/resources.cpp
index 0e12460..781df2b 100644
--- a/minuitwrp/resources.c
+++ b/minuitwrp/resources.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include <fcntl.h>
@@ -23,32 +24,25 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/types.h>
-#include <string.h>
 
 #include <linux/fb.h>
 #include <linux/kd.h>
 
-#include <pixelflinger/pixelflinger.h>
-
 #include <png.h>
+
+#include <pixelflinger/pixelflinger.h>
+extern "C" {
 #include "jpeglib.h"
-
-#include "minui.h"
-
-// libpng gives "undefined reference to 'pow'" errors, and I have no
-// idea how to convince the build system to link with -lm.  We don't
-// need this functionality (it's used for gamma adjustment) so provide
-// a dummy implementation to satisfy the linker.
-double pow(double x, double y) {
-    return x;
 }
+#include "minui.h"
 
 #define SURFACE_DATA_ALIGNMENT 8
 
 static GGLSurface* malloc_surface(size_t data_size) {
-    unsigned char* temp = malloc(sizeof(GGLSurface) + data_size + SURFACE_DATA_ALIGNMENT);
+    size_t size = sizeof(GGLSurface) + data_size + SURFACE_DATA_ALIGNMENT;
+    unsigned char* temp = reinterpret_cast<unsigned char*>(malloc(size));
     if (temp == NULL) return NULL;
-    GGLSurface* surface = (GGLSurface*) temp;
+    GGLSurface* surface = reinterpret_cast<GGLSurface*>(temp);
     surface->data = temp + sizeof(GGLSurface) +
         (SURFACE_DATA_ALIGNMENT - (sizeof(GGLSurface) % SURFACE_DATA_ALIGNMENT));
     return surface;
@@ -59,9 +53,10 @@
     char resPath[256];
     unsigned char header[8];
     int result = 0;
+    int color_type, bit_depth;
+    size_t bytesRead;
 
     snprintf(resPath, sizeof(resPath)-1, TWRES "images/%s.png", name);
-    printf("open_png %s\n", resPath);
     resPath[sizeof(resPath)-1] = '\0';
     FILE* fp = fopen(resPath, "rb");
     if (fp == NULL) {
@@ -72,7 +67,7 @@
         }
     }
 
-    size_t bytesRead = fread(header, 1, sizeof(header), fp);
+    bytesRead = fread(header, 1, sizeof(header), fp);
     if (bytesRead != sizeof(header)) {
         result = -2;
         goto exit;
@@ -104,13 +99,12 @@
     png_set_sig_bytes(*png_ptr, sizeof(header));
     png_read_info(*png_ptr, *info_ptr);
 
-    int color_type, bit_depth;
     png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth,
             &color_type, NULL, NULL, NULL);
 
     *channels = png_get_channels(*png_ptr, *info_ptr);
 
-    /*if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) {
+    if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) {
         // 8-bit RGB images: great, nothing to do.
     } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) {
         // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray.
@@ -122,14 +116,8 @@
         // general.
         png_set_palette_to_rgb(*png_ptr);
         *channels = 3;
-    } else {
-        fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n",
-                bit_depth, *channels, color_type);
-        result = -7;
-        goto exit;
-    }*/
-    if (color_type == PNG_COLOR_TYPE_PALETTE) {
-        png_set_palette_to_rgb(png_ptr);
+    } else if (color_type == PNG_COLOR_TYPE_PALETTE) {
+        png_set_palette_to_rgb(*png_ptr);
     }
 
     *fpp = fp;
@@ -153,12 +141,10 @@
 // framebuffer pixel format; they need to be modified if the
 // framebuffer format changes (but nothing else should).
 
-// Allocate and return a gr_surface sufficient for storing an image of
+// Allocate and return a GRSurface* sufficient for storing an image of
 // the indicated size in the framebuffer pixel format.
 static GGLSurface* init_display_surface(png_uint_32 width, png_uint_32 height) {
-    GGLSurface* surface;
-
-    surface = (GGLSurface*) malloc_surface(width * height * 4);
+    GGLSurface* surface = malloc_surface(width * height * 4);
     if (surface == NULL) return NULL;
 
     surface->version = sizeof(GGLSurface);
@@ -222,6 +208,8 @@
     png_uint_32 width, height;
     png_byte channels;
     FILE* fp;
+    unsigned char* p_row;
+    unsigned int y;
 
     *pSurface = NULL;
 
@@ -234,8 +222,15 @@
         goto exit;
     }
 
-    unsigned char* p_row = malloc(width * 4);
-    unsigned int y;
+#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
+    png_set_bgr(png_ptr);
+#endif
+
+    p_row = reinterpret_cast<unsigned char*>(malloc(width * 4));
+    if (p_row == NULL) {
+        result = -9;
+        goto exit;
+    }
     for (y = 0; y < height; ++y) {
         png_read_row(png_ptr, p_row, NULL);
         transform_rgb_to_draw(p_row, surface->data + y * width * 4, channels, width);
@@ -258,9 +253,11 @@
 
 int res_create_surface_jpg(const char* name, gr_surface* pSurface) {
     GGLSurface* surface = NULL;
-    int result = 0;
+    int result = 0, y;
     struct jpeg_decompress_struct cinfo;
     struct jpeg_error_mgr jerr;
+    unsigned char* pData;
+    size_t width, height, stride, pixelSize;
 
     FILE* fp = fopen(name, "rb");
     if (fp == NULL) {
@@ -288,18 +285,19 @@
     /* Start decompressor */
     (void) jpeg_start_decompress(&cinfo);
 
-    size_t width = cinfo.image_width;
-    size_t height = cinfo.image_height;
-    size_t stride = 4 * width;
-    size_t pixelSize = stride * height;
+    width = cinfo.image_width;
+    height = cinfo.image_height;
+    stride = 4 * width;
+    pixelSize = stride * height;
 
-    surface = malloc(sizeof(GGLSurface) + pixelSize);
+    surface = reinterpret_cast<GGLSurface*>(malloc(sizeof(GGLSurface) + pixelSize));
+    //p_row = reinterpret_cast<unsigned char*>(malloc(width * 4));
     if (surface == NULL) {
         result = -8;
         goto exit;
     }
 
-    unsigned char* pData = (unsigned char*) (surface + 1);
+    pData = (unsigned char*) (surface + 1);
     surface->version = sizeof(GGLSurface);
     surface->width = width;
     surface->height = height;
@@ -307,7 +305,6 @@
     surface->data = pData;
     surface->format = GGL_PIXEL_FORMAT_RGBX_8888;
 
-    int y;
     for (y = 0; y < (int) height; ++y) {
         unsigned char* pRow = pData + y * stride;
         jpeg_read_scanlines(&cinfo, &pRow, 1);
@@ -320,10 +317,17 @@
             unsigned char g = pRow[sx + 1];
             unsigned char b = pRow[sx + 2];
             unsigned char a = 0xff;
+#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
+            pRow[dx    ] = b; // r
+            pRow[dx + 1] = g; // g
+            pRow[dx + 2] = r; // b
+            pRow[dx + 3] = a;
+#else
             pRow[dx    ] = r; // r
             pRow[dx + 1] = g; // g
             pRow[dx + 2] = b; // b
             pRow[dx + 3] = a;
+#endif
         }
     }
     *pSurface = (gr_surface) surface;
diff --git a/minuitwrp/truetype.c b/minuitwrp/truetype.cpp
similarity index 88%
rename from minuitwrp/truetype.c
rename to minuitwrp/truetype.cpp
index d9ed019..18635a8 100644
--- a/minuitwrp/truetype.c
+++ b/minuitwrp/truetype.cpp
@@ -88,8 +88,8 @@
 
 static uint32_t fnv_hash(void *data, uint32_t len)
 {
-    uint8_t *d8 = data;
-    uint32_t *d32 = data;
+    uint8_t *d8 = (uint8_t *)data;
+    uint32_t *d32 = (uint32_t *)data;
     uint32_t i, max;
     uint32_t hash = offset_basis;
 
@@ -118,12 +118,12 @@
     return cur_hash;
 }
 
-int utf8_to_unicode(unsigned char* pIn, unsigned int *pOut)
+int utf8_to_unicode(const char* pIn, unsigned int *pOut)
 {
     int utf_bytes = 1;
     unsigned int unicode = 0;
     unsigned char tmp;
-    tmp = *pIn++;
+    tmp = (unsigned char)*pIn++;
     if (tmp < 0x80)
     {
         *pOut = tmp;
@@ -157,27 +157,27 @@
 
 static bool gr_ttf_string_cache_equals(void *keyA, void *keyB)
 {
-    StringCacheKey *a = keyA;
-    StringCacheKey *b = keyB;
+    StringCacheKey *a = (StringCacheKey *)keyA;
+    StringCacheKey *b = (StringCacheKey *)keyB;
     return a->max_width == b->max_width && strcmp(a->text, b->text) == 0;
 }
 
 static int gr_ttf_string_cache_hash(void *key)
 {
-    StringCacheKey *k = key;
+    StringCacheKey *k = (StringCacheKey *)key;
     return fnv_hash(k->text, strlen(k->text));
 }
 
 static bool gr_ttf_font_cache_equals(void *keyA, void *keyB)
 {
-    TrueTypeFontKey *a = keyA;
-    TrueTypeFontKey *b = keyB;
+    TrueTypeFontKey *a = (TrueTypeFontKey *)keyA;
+    TrueTypeFontKey *b = (TrueTypeFontKey *)keyB;
     return (a->size == b->size) && (a->dpi == b->dpi) && !strcmp(a->path, b->path);
 }
 
 static int gr_ttf_font_cache_hash(void *key)
 {
-    TrueTypeFontKey *k = key;
+    TrueTypeFontKey *k = (TrueTypeFontKey *)key;
 
     uint32_t hash = fnv_hash(k->path, strlen(k->path));
     hash = fnv_hash_add(hash, k->size);
@@ -189,6 +189,7 @@
 {
     int error;
     TrueTypeFont *res = NULL;
+    TrueTypeFontKey *key = NULL;
 
     pthread_mutex_lock(&font_data.mutex);
 
@@ -200,7 +201,7 @@
             .path = (char*)filename
         };
 
-        res = hashmapGet(font_data.fonts, &k);
+        res = (TrueTypeFont *)hashmapGet(font_data.fonts, &k);
         if(res)
         {
             ++res->refcount;
@@ -234,7 +235,7 @@
          goto exit;
     }
 
-    res = malloc(sizeof(TrueTypeFont));
+    res = (TrueTypeFont *)malloc(sizeof(TrueTypeFont));
     memset(res, 0, sizeof(TrueTypeFont));
     res->type = FONT_TYPE_TTF;
     res->size = size;
@@ -250,7 +251,7 @@
     if(!font_data.fonts)
         font_data.fonts = hashmapCreate(4, gr_ttf_font_cache_hash, gr_ttf_font_cache_equals);
 
-    TrueTypeFontKey *key = malloc(sizeof(TrueTypeFontKey));
+    key = (TrueTypeFontKey *)malloc(sizeof(TrueTypeFontKey));
     memset(key, 0, sizeof(TrueTypeFontKey));
     key->path = strdup(filename);
     key->size = size;
@@ -270,7 +271,7 @@
     if (!font)
         return NULL;
 
-    TrueTypeFont *f = font;
+    TrueTypeFont *f = (TrueTypeFont *)font;
     float scale_value = (float)(max_width) / (float)(measured_width);
     int new_size = ((int)((float)f->size * scale_value)) - 1;
     if (new_size < 1)
@@ -280,22 +281,22 @@
     return gr_ttf_loadFont(file, new_size, dpi);
 }
 
-static bool gr_ttf_freeFontCache(void *key, void *value, void *context)
+static bool gr_ttf_freeFontCache(void *key, void *value, void *context __unused)
 {
-    TrueTypeCacheEntry *e = value;
+    TrueTypeCacheEntry *e = (TrueTypeCacheEntry *)value;
     FT_Done_Glyph((FT_Glyph)e->glyph);
     free(e);
     free(key);
     return true;
 }
 
-static bool gr_ttf_freeStringCache(void *key, void *value, void *context)
+static bool gr_ttf_freeStringCache(void *key, void *value, void *context __unused)
 {
-    StringCacheKey *k = key;
+    StringCacheKey *k = (StringCacheKey *)key;
     free(k->text);
     free(k);
 
-    StringCacheEntry *e = value;
+    StringCacheEntry *e = (StringCacheEntry *)value;
     free(e->surface.data);
     free(e);
     return true;
@@ -305,7 +306,7 @@
 {
     pthread_mutex_lock(&font_data.mutex);
 
-    TrueTypeFont *d = font;
+    TrueTypeFont *d = (TrueTypeFont *)font;
 
     if(--d->refcount == 0)
     {
@@ -334,12 +335,12 @@
 
 static TrueTypeCacheEntry *gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index)
 {
-    return hashmapGet(font->glyph_cache, &char_index);
+    return (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index);
 }
 
 static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index)
 {
-    TrueTypeCacheEntry *res = hashmapGet(font->glyph_cache, &char_index);
+    TrueTypeCacheEntry *res = (TrueTypeCacheEntry *)hashmapGet(font->glyph_cache, &char_index);
     if(!res)
     {
         int error = FT_Load_Glyph(font->face, char_index, FT_LOAD_RENDER);
@@ -357,12 +358,12 @@
             return NULL;
         }
 
-        res = malloc(sizeof(TrueTypeCacheEntry));
+        res = (TrueTypeCacheEntry *)malloc(sizeof(TrueTypeCacheEntry));
         memset(res, 0, sizeof(TrueTypeCacheEntry));
         res->glyph = glyph;
         FT_Glyph_Get_CBox((FT_Glyph)glyph, FT_GLYPH_BBOX_PIXELS, &res->bbox);
 
-        int *key = malloc(sizeof(int));
+        int *key = (int *)malloc(sizeof(int));
         *key = char_index;
 
         hashmapPut(font->glyph_cache, key, res);
@@ -373,7 +374,7 @@
 
 static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base)
 {
-    int y;
+    unsigned y;
     uint8_t *src_itr = glyph->bitmap.buffer;
     uint8_t *dest_itr = dest->data;
 
@@ -467,7 +468,7 @@
     int *char_idxs;
     int char_idxs_len = 0;
 
-    char_idxs = malloc(strlen(text) * sizeof(int));
+    char_idxs = (int *)malloc(strlen(text) * sizeof(int));
 
     while(*text_itr)
     {
@@ -509,7 +510,7 @@
 
     height = font->max_height;
 
-    data = malloc(total_w*height);
+    data = (uint8_t *)malloc(total_w*height);
     memset(data, 0, total_w*height);
     x = 0;
     prev_idx = 0;
@@ -518,7 +519,7 @@
     surface->width = total_w;
     surface->height = height;
     surface->stride = total_w;
-    surface->data = (void*)data;
+    surface->data = (GGLubyte*)data;
     surface->format = GGL_PIXEL_FORMAT_A_8;
 
     for(i = 0; i < char_idxs_len; ++i)
@@ -552,7 +553,7 @@
         .max_width = max_width
     };
 
-    return hashmapGet(font->string_cache, &k);
+    return (StringCacheEntry *)hashmapGet(font->string_cache, &k);
 }
 
 static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width)
@@ -563,10 +564,10 @@
         .max_width = max_width
     };
 
-    res = hashmapGet(font->string_cache, &k);
+    res = (StringCacheEntry *)hashmapGet(font->string_cache, &k);
     if(!res)
     {
-        res = malloc(sizeof(StringCacheEntry));
+        res = (StringCacheEntry *)malloc(sizeof(StringCacheEntry));
         memset(res, 0, sizeof(StringCacheEntry));
         res->rendered_bytes = gr_ttf_render_text(font, &res->surface, text, max_width);
         if(res->rendered_bytes < 0)
@@ -575,7 +576,7 @@
             return NULL;
         }
 
-        StringCacheKey *new_key = malloc(sizeof(StringCacheKey));
+        StringCacheKey *new_key = (StringCacheKey *)malloc(sizeof(StringCacheKey));
         memset(new_key, 0, sizeof(StringCacheKey));
         new_key->max_width = max_width;
         new_key->text = strdup(text);
@@ -633,11 +634,11 @@
 
 int gr_ttf_measureEx(const char *s, void *font)
 {
-    TrueTypeFont *f = font;
+    TrueTypeFont *f = (TrueTypeFont *)font;
     int res = -1;
 
     pthread_mutex_lock(&f->mutex);
-    StringCacheEntry *e = gr_ttf_string_cache_get(font, s, -1);
+    StringCacheEntry *e = gr_ttf_string_cache_get(f, s, -1);
     if(e)
         res = e->surface.width;
     pthread_mutex_unlock(&f->mutex);
@@ -647,7 +648,7 @@
 
 int gr_ttf_maxExW(const char *s, void *font, int max_width)
 {
-    TrueTypeFont *f = font;
+    TrueTypeFont *f = (TrueTypeFont *)font;
     TrueTypeCacheEntry *ent;
     int max_bytes = 0, total_w = 0;
     int utf_bytes, prev_utf_bytes = 0;
@@ -658,7 +659,7 @@
 
     pthread_mutex_lock(&f->mutex);
 
-    e = gr_ttf_string_cache_peek(font, s, max_width);
+    e = gr_ttf_string_cache_peek(f, s, max_width);
     if(e)
     {
         max_bytes = e->rendered_bytes;
@@ -699,8 +700,8 @@
 
 int gr_ttf_textExWH(void *context, int x, int y, const char *s, void *pFont, int max_width, int max_height)
 {
-    GGLContext *gl = context;
-    TrueTypeFont *font = pFont;
+    GGLContext *gl = (GGLContext *)context;
+    TrueTypeFont *font = (TrueTypeFont *)pFont;
 
     // not actualy max width, but max_width + x
     if(max_width != -1)
@@ -749,7 +750,7 @@
 int gr_ttf_getMaxFontHeight(void *font)
 {
     int res;
-    TrueTypeFont *f = font;
+    TrueTypeFont *f = (TrueTypeFont *)font;
 
     pthread_mutex_lock(&f->mutex);
 
@@ -761,19 +762,19 @@
     return res;
 }
 
-static bool gr_ttf_dump_stats_count_string_cache(void *key, void *value, void *context)
+static bool gr_ttf_dump_stats_count_string_cache(void *key __unused, void *value, void *context)
 {
-    int *string_cache_size = context;
-    StringCacheEntry *e = value;
+    int *string_cache_size = (int *)context;
+    StringCacheEntry *e = (StringCacheEntry *)value;
     *string_cache_size += e->surface.height*e->surface.width + sizeof(StringCacheEntry);
     return true;
 }
 
 static bool gr_ttf_dump_stats_font(void *key, void *value, void *context)
 {
-    TrueTypeFontKey *k = key;
-    TrueTypeFont *f = value;
-    int *total_string_cache_size = context;
+    TrueTypeFontKey *k = (TrueTypeFontKey *)key;
+    TrueTypeFont *f = (TrueTypeFont *)value;
+    int *total_string_cache_size = (int *)context;
     int string_cache_size = 0;
 
     pthread_mutex_lock(&f->mutex);