From fbb4353a247157d32208f8f133cd1ee42f4fbc49 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Mon, 28 Dec 2015 21:54:50 +0100 Subject: [PATCH] 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 --- data.cpp | 2 +- gui/action.cpp | 3 +- gui/animation.cpp | 2 +- gui/blanktimer.cpp | 10 +- gui/button.cpp | 2 +- gui/checkbox.cpp | 2 +- gui/console.cpp | 2 +- gui/fileselector.cpp | 2 +- gui/fill.cpp | 2 +- gui/gui.cpp | 2 +- gui/image.cpp | 2 +- gui/input.cpp | 28 +- gui/keyboard.cpp | 6 +- gui/listbox.cpp | 2 +- gui/mousecursor.cpp | 2 +- gui/pages.cpp | 2 +- gui/partitionlist.cpp | 2 +- gui/patternpassword.cpp | 2 +- gui/progressbar.cpp | 2 +- gui/resources.cpp | 2 +- gui/resources.hpp | 2 +- gui/scrolllist.cpp | 2 +- gui/slider.cpp | 2 +- gui/slidervalue.cpp | 4 +- gui/terminal.cpp | 8 +- gui/text.cpp | 10 +- gui/textbox.cpp | 4 +- minuitwrp/Android.mk | 44 +- minuitwrp/{events.c => events.cpp} | 2 +- minuitwrp/graphics.c | 754 ------------------ minuitwrp/graphics.cpp | 416 ++++++++++ minuitwrp/graphics.h | 44 + minuitwrp/graphics_adf.cpp | 285 +++++++ minuitwrp/graphics_drm.cpp | 492 ++++++++++++ minuitwrp/graphics_fbdev.cpp | 281 +++++++ ...raphics_overlay.c => graphics_overlay.cpp} | 502 ++++++++---- .../{graphics_utils.c => graphics_utils.cpp} | 9 +- minuitwrp/minui.h | 24 +- minuitwrp/{resources.c => resources.cpp} | 84 +- minuitwrp/{truetype.c => truetype.cpp} | 91 +-- 40 files changed, 2067 insertions(+), 1072 deletions(-) rename minuitwrp/{events.c => events.cpp} (99%) delete mode 100644 minuitwrp/graphics.c create mode 100644 minuitwrp/graphics.cpp create mode 100644 minuitwrp/graphics.h create mode 100644 minuitwrp/graphics_adf.cpp create mode 100644 minuitwrp/graphics_drm.cpp create mode 100644 minuitwrp/graphics_fbdev.cpp rename minuitwrp/{graphics_overlay.c => graphics_overlay.cpp} (50%) rename minuitwrp/{graphics_utils.c => graphics_utils.cpp} (91%) rename minuitwrp/{resources.c => resources.cpp} (89%) rename minuitwrp/{truetype.c => truetype.cpp} (88%) diff --git a/data.cpp b/data.cpp index 77e8f8de..07f9e61d 100644 --- a/data.cpp +++ b/data.cpp @@ -59,9 +59,9 @@ extern "C" { #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 8895e401..240db8f2 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 888b4ab0..d45373d8 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 06208e27..4662b1fa 100644 --- a/gui/blanktimer.cpp +++ b/gui/blanktimer.cpp @@ -26,9 +26,9 @@ using namespace std; #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 @@ void blanktimer::checkForTimeout() { 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 @@ void blanktimer::resetTimerAndUnblank(void) { 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 a4c1b52b..45614e46 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 1760bac2..e79f0cdc 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 b5204fb7..6f375ff2 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 a97ff34b..23f235c7 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 b315cd08..d0a1cfda 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 7cf21b0a..f8a6a73e 100644 --- a/gui/gui.cpp +++ b/gui/gui.cpp @@ -38,9 +38,9 @@ extern "C" { #include "../twcommon.h" -#include "../minuitwrp/minui.h" #include } +#include "../minuitwrp/minui.h" #include "rapidxml.hpp" #include "objects.hpp" diff --git a/gui/image.cpp b/gui/image.cpp index 8b43aaa3..2107d550 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 68bd163b..c12ecc2b 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 @@ int GUIInput::HandleTextLocation(int x) 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 @@ int GUIInput::HandleTextLocation(int x) 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 @@ int GUIInput::HandleTextLocation(int x) 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 @@ int GUIInput::HandleTextLocation(int x) 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 @@ int GUIInput::HandleTextLocation(int x) } 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 @@ int GUIInput::HandleTextLocation(int x) } 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 @@ int GUIInput::HandleTextLocation(int x) 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 @@ int GUIInput::Render(void) 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 @@ int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y) for(index=0; index x) { if (index > 0) mCursorLocation = index - 1; diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp index 3b8fdc9a..4a78ad79 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 @@ void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH) 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 @@ void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH) 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 b0d2731f..e10fee72 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 84e6322a..bd730df6 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 c4556623..4a4c5236 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 102802d7..ff207fa9 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 a6ab8312..96054c15 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 a478a40d..fc2a4976 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 a8f41991..e7611dd9 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 ce06d967..4548c10b 100644 --- a/gui/resources.hpp +++ b/gui/resources.hpp @@ -49,7 +49,7 @@ public: 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 6e974f20..291b3820 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 6ee2024d..59b295bd 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 8a44a3cb..088620a2 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 @@ int GUISliderValue::measureText(const std::string& str) 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 044782e4..29b0e846 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 @@ void GUITerminal::RenderItem(size_t itemindex, int yPos, bool selected) // 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 @@ void GUITerminal::InitAndResize() // 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 9898e283..6498af62 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 @@ GUIText::GUIText(xml_node<>* node) // 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 @@ int GUIText::Render(void) void* fontResource = NULL; if (mFont) fontResource = mFont->GetResource(); + else + return -1; mLastValue = gui_parse_text(mText); string displayValue = mLastValue; @@ -98,7 +102,7 @@ int GUIText::Render(void) 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 @@ int GUIText::GetCurrentBounds(int& w, int& h) 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 277297fe..2e2512c5 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 @@ void GUITextBox::RenderItem(size_t itemindex, int yPos, bool selected __unused) // 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 01225c32..39c61c40 100644 --- a/minuitwrp/Android.mk +++ b/minuitwrp/Android.mk @@ -2,12 +2,20 @@ LOCAL_PATH := $(call my-dir) 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 @@ ifeq ($(TW_TARGET_USES_QCOM_BSP), true) 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 @@ ifeq ($(subst ",,$(TARGET_RECOVERY_PIXEL_FORMAT)),RGB_565) 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 @@ ifeq ($(TW_DISABLE_TTF), true) $(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 4e10e72f..d4ca0abb 100644 --- a/minuitwrp/events.c +++ b/minuitwrp/events.cpp @@ -243,7 +243,7 @@ static int vk_init(struct ev *e) 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 fb86c145..00000000 --- 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 -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#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 00000000..47325d01 --- /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 +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#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 00000000..a4115fd5 --- /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 00000000..b71bed2a --- /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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "graphics.h" +#include + +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(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(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 00000000..9bbf7e98 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "minui.h" +#include "graphics.h" +#include + +#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 00000000..10ef4fec --- /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 +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "minui.h" +#include "graphics.h" +#include + +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(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.cpp similarity index 50% rename from minuitwrp/graphics_overlay.c rename to minuitwrp/graphics_overlay.cpp index 723ffa2d..5445b6f6 100644 --- a/minuitwrp/graphics_overlay.c +++ b/minuitwrp/graphics_overlay.cpp @@ -1,40 +1,29 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (C) 2014 The Android Open Source Project * - * 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. + * 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 * - * 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. -*/ + * 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 #include +#include #include - #include + #include #include +#include #include #include #include @@ -47,15 +36,32 @@ #include #endif +#include "minui.h" +#include "graphics.h" #include -#include "minui.h" - #define MDP_V4_0 400 +#define MAX_DISPLAY_DIM 2048 -#ifdef MSM_BSP +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; @@ -72,23 +78,31 @@ 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; + 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 bool overlay_supported = false; -static bool isMDP5 = false; +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"))) { @@ -104,22 +118,100 @@ bool target_has_overlay(char *version) isMDP5 = true; } } - if (overlay_supported) printf("Using qcomm overlay\n"); + return overlay_supported; } -bool isTargetMdp5() -{ - if (isMDP5) - return true; +minui_backend* open_overlay() { + fb_fix_screeninfo fi; + int fd; - return false; + 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) { - if (!overlay_supported) - return -EINVAL; - int ret = 0; if (mem_info.mem_buf) @@ -144,8 +236,6 @@ int free_ion_mem(void) { 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; @@ -195,13 +285,20 @@ int alloc_ion_mem(unsigned int size) return 0; } -int allocate_overlay(int fd, GGLSurface gr_fb[]) +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 (!overlay_supported) - return -EINVAL; - if (!isDisplaySplit()) { // Check if overlay is already allocated if (MSMFB_NEW_REQUEST == overlayL_id) { @@ -210,13 +307,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) 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.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[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.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; @@ -228,13 +325,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) overlayL_id = overlayL.id; } } else { - float xres = getFbXres(); + float xres = vi.xres; int lSplit = getLeftSplit(); float lSplitRatio = lSplit / xres; - float lCropWidth = gr_fb[0].width * lSplitRatio; + float lCropWidth = gr_fb.width * lSplitRatio; int lWidth = lSplit; - int rWidth = gr_fb[0].width - lSplit; - int height = gr_fb[0].height; + int rWidth = gr_fb.width - lSplit; + int height = gr_fb.height; if (MSMFB_NEW_REQUEST == overlayL_id) { @@ -243,13 +340,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) 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.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[0].height; + overlayL.src_rect.h = gr_fb.height; overlayL.dst_rect.x = 0; overlayL.dst_rect.y = 0; overlayL.dst_rect.w = lWidth; @@ -270,13 +367,13 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) 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.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[0].width - lCropWidth; - overlayR.src_rect.h = gr_fb[0].height; + 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; @@ -297,64 +394,8 @@ int allocate_overlay(int fd, GGLSurface gr_fb[]) return 0; } -int free_overlay(int fd) +int overlay_display_frame(int fd, void* data, size_t size) { - 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; @@ -376,6 +417,7 @@ int overlay_display_frame(int fd, GGLubyte* data, size_t size) 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 { @@ -426,38 +468,186 @@ int overlay_display_frame(int fd, GGLubyte* data, size_t size) 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; +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) { - 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"); + } + } + + 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) -{ - return -EINVAL; +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(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(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; } -#endif //#ifdef MSM_BSP +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 ea1182dd..6ce57048 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 @@ int gr_save_screenshot(const char *dest) 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 25a785a5..018f3274 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -18,6 +18,16 @@ #define _MINUI_H_ #include "../gui/placement.h" +#include + +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_width(void); 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_fill(int x, int y, int w, int h); 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 @@ int res_create_surface(const char* name, gr_surface* pSurface); 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 89% rename from minuitwrp/resources.c rename to minuitwrp/resources.cpp index 0e124608..781df2b0 100644 --- a/minuitwrp/resources.c +++ b/minuitwrp/resources.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include @@ -23,32 +24,25 @@ #include #include #include -#include #include #include -#include - #include + +#include +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(malloc(size)); if (temp == NULL) return NULL; - GGLSurface* surface = (GGLSurface*) temp; + GGLSurface* surface = reinterpret_cast(temp); surface->data = temp + sizeof(GGLSurface) + (SURFACE_DATA_ALIGNMENT - (sizeof(GGLSurface) % SURFACE_DATA_ALIGNMENT)); return surface; @@ -59,9 +53,10 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, 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 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, } } - 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 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, 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 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, // 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 @@ static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, // 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 @@ int res_create_surface_png(const char* name, gr_surface* pSurface) { png_uint_32 width, height; png_byte channels; FILE* fp; + unsigned char* p_row; + unsigned int y; *pSurface = NULL; @@ -234,8 +222,15 @@ int res_create_surface_png(const char* name, gr_surface* pSurface) { 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(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_png(const char* name, gr_surface* pSurface) { 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 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { /* 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(malloc(sizeof(GGLSurface) + pixelSize)); + //p_row = reinterpret_cast(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 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { 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 @@ int res_create_surface_jpg(const char* name, gr_surface* pSurface) { 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 d9ed0198..18635a88 100644 --- a/minuitwrp/truetype.c +++ b/minuitwrp/truetype.cpp @@ -88,8 +88,8 @@ static const uint32_t offset_basis = 2166136261U; 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 @@ static inline uint32_t fnv_hash_add(uint32_t cur_hash, uint32_t word) 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 @@ int utf8_to_unicode(unsigned char* pIn, unsigned int *pOut) 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 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) { int error; TrueTypeFont *res = NULL; + TrueTypeFontKey *key = NULL; pthread_mutex_lock(&font_data.mutex); @@ -200,7 +201,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) .path = (char*)filename }; - res = hashmapGet(font_data.fonts, &k); + res = (TrueTypeFont *)hashmapGet(font_data.fonts, &k); if(res) { ++res->refcount; @@ -234,7 +235,7 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) 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 @@ void *gr_ttf_loadFont(const char *filename, int size, int dpi) 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 @@ void *gr_ttf_scaleFont(void *font, int max_width, int measured_width) 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 @@ void *gr_ttf_scaleFont(void *font, int max_width, int measured_width) 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 @@ void gr_ttf_freeFont(void *font) { pthread_mutex_lock(&font_data.mutex); - TrueTypeFont *d = font; + TrueTypeFont *d = (TrueTypeFont *)font; if(--d->refcount == 0) { @@ -334,12 +335,12 @@ void gr_ttf_freeFont(void *font) 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 @@ static TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_i 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 TrueTypeCacheEntry *gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_i 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 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha 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 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha 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 @@ static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const cha 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 @@ static StringCacheEntry *gr_ttf_string_cache_peek(TrueTypeFont *font, const char .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 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char .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 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char 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 @@ static StringCacheEntry *gr_ttf_string_cache_get(TrueTypeFont *font, const char 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_measureEx(const char *s, void *font) 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 @@ int gr_ttf_maxExW(const char *s, void *font, int max_width) 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_maxExW(const char *s, void *font, int max_width) 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_textExWH(void *context, int x, int y, const char *s, void *pFont, int int gr_ttf_getMaxFontHeight(void *font) { int res; - TrueTypeFont *f = font; + TrueTypeFont *f = (TrueTypeFont *)font; pthread_mutex_lock(&f->mutex); @@ -761,19 +762,19 @@ int gr_ttf_getMaxFontHeight(void *font) 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);