diff options
author | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-05-01 10:07:00 +0200 |
---|---|---|
committer | jenkins4kodi <jenkins4kodi@users.noreply.github.com> | 2015-05-01 10:07:00 +0200 |
commit | 1de18d9d3b75e880b5b12c6858172b145f99771b (patch) | |
tree | 2a41dab87d35d5f323bb5acd923594bef61a824a | |
parent | 70f4e3f6e201af34c3e455be7e1f38201234132f (diff) | |
parent | 31e87e2e6dd21c9d8ea5c7412e4401a114392743 (diff) |
Merge pull request #6996 from mk01/master
-rw-r--r-- | xbmc/windowing/egl/EGLNativeTypeIMX.cpp | 98 | ||||
-rw-r--r-- | xbmc/windowing/egl/EGLNativeTypeIMX.h | 6 |
2 files changed, 99 insertions, 5 deletions
diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp index 6ab42b1958..4a384f8a73 100644 --- a/xbmc/windowing/egl/EGLNativeTypeIMX.cpp +++ b/xbmc/windowing/egl/EGLNativeTypeIMX.cpp @@ -43,6 +43,7 @@ CEGLNativeTypeIMX::CEGLNativeTypeIMX() : m_display(NULL) , m_window(NULL) + , m_sar(0) { } @@ -130,6 +131,7 @@ void CEGLNativeTypeIMX::Initialize() close(fd); + m_sar = GetMonitorSAR(); return; } @@ -266,6 +268,21 @@ bool CEGLNativeTypeIMX::SetNativeResolution(const RESOLUTION_INFO &res) return true; } +bool CEGLNativeTypeIMX::FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions) +{ + for (int i = 0; i < (int)resolutions.size(); i++) + { + if(resolutions[i].iScreenWidth == res.iScreenWidth && + resolutions[i].iScreenHeight == res.iScreenHeight && + resolutions[i].fRefreshRate == res.fRefreshRate && + (resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) == (res.dwFlags & D3DPRESENTFLAG_MODEMASK)) + { + return true; + } + } + return false; +} + bool CEGLNativeTypeIMX::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutions) { if (m_readonly) @@ -273,17 +290,25 @@ bool CEGLNativeTypeIMX::ProbeResolutions(std::vector<RESOLUTION_INFO> &resolutio std::string valstr; SysfsUtils::GetString("/sys/class/graphics/fb0/modes", valstr); - std::vector<std::string> probe_str; - probe_str = StringUtils::Split(valstr, "\n"); + std::vector<std::string> probe_str = StringUtils::Split(valstr, "\n"); + + // lexical order puts the modes list into our preferred + // order and by later filtering through FindMatchingResolution() + // we make sure we read _all_ S modes, following U and V modes + // while list will hold unique resolutions only + std::sort(probe_str.begin(), probe_str.end()); resolutions.clear(); RESOLUTION_INFO res; for (size_t i = 0; i < probe_str.size(); i++) { - if(!StringUtils::StartsWith(probe_str[i], "S:")) + if(!StringUtils::StartsWith(probe_str[i], "S:") && !StringUtils::StartsWith(probe_str[i], "U:") && + !StringUtils::StartsWith(probe_str[i], "V:")) continue; + if(ModeToResolution(probe_str[i], &res)) - resolutions.push_back(res); + if(!FindMatchingResolution(res, resolutions)) + resolutions.push_back(res); } return resolutions.size() > 0; } @@ -304,6 +329,68 @@ bool CEGLNativeTypeIMX::ShowWindow(bool show) return false; } +float CEGLNativeTypeIMX::GetMonitorSAR() +{ + FILE *f_edid; + char *str = NULL; + unsigned char p; + size_t n; + int done = 0; + + // kernels <= 3.18 use ./soc0/soc.0 + // kernels > 3.18 use ./soc0/soc + f_edid = fopen("/sys/devices/soc0/soc/20e0000.hdmi_video/edid", "r"); + if(!f_edid) + f_edid = fopen("/sys/devices/soc0/soc.0/20e0000.hdmi_video/edid", "r"); + + if(!f_edid) + return 0; + + // we need to convert mxc_hdmi output format to binary array + // mxc_hdmi provides the EDID as space delimited 1bytes blocks + // exported as text with format specifier %x eg: + // 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x4C 0x2D 0x7A 0x0A 0x00 0x00 0x00 0x00 + // + // this translates into the inner cycle where we move pointer first + // with +2 to skip '0x', + // we sscanf actual data (eg FF) into a byte, + // we move over the FF and delimiting space with +3 + // + // this parses whole 512 byte long info into internal binary array for future + // reference and use. current use is only to grab screen's physical params + // at EGL init. + while(getline(&str, &n, f_edid) > 0) + { + char *c = str; + while(*c != '\n' && done < 512) + { + c += 2; + sscanf(c, "%hhx", &p); + m_edid[done++] = p; + c += 3; + } + if (str) + free(str); + str = NULL; + } + fclose(f_edid); + + // info related to 'Basic display parameters.' is at offset 0x14-0x18. + // where W is 2nd byte, H 3rd. + int cmWidth = (int)*(m_edid +EDID_STRUCT_DISPLAY +1); + int cmHeight = (int)*(m_edid +EDID_STRUCT_DISPLAY +2); + if (cmHeight > 0) + { + float t_sar = (float) cmWidth / cmHeight; + if (t_sar >= 0.33 && t_sar <= 3.0) + return t_sar; + } + + // if we end up here, H/W values or final SAR are useless + // return 0 and use 1.0f as PR for all resolutions + return 0; +} + bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) const { if (!res) @@ -338,7 +425,8 @@ bool CEGLNativeTypeIMX::ModeToResolution(std::string mode, RESOLUTION_INFO *res) res->iScreen = 0; res->bFullScreen = true; res->iSubtitles = (int)(0.965 * res->iHeight); - res->fPixelRatio = 1.0f; + + res->fPixelRatio = !m_sar ? 1.0f : (float)m_sar / res->iScreenWidth * res->iScreenHeight; res->strMode = StringUtils::Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate, res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : ""); res->strId = mode; diff --git a/xbmc/windowing/egl/EGLNativeTypeIMX.h b/xbmc/windowing/egl/EGLNativeTypeIMX.h index beff4f5cbc..ca738e3cfd 100644 --- a/xbmc/windowing/egl/EGLNativeTypeIMX.h +++ b/xbmc/windowing/egl/EGLNativeTypeIMX.h @@ -24,6 +24,8 @@ #include <EGL/egl.h> #include "EGLNativeType.h" +#define EDID_STRUCT_DISPLAY 0x14 + class CEGLNativeTypeIMX : public CEGLNativeType { public: @@ -52,8 +54,12 @@ public: protected: bool m_readonly; + float m_sar; bool ModeToResolution(std::string mode, RESOLUTION_INFO *res) const; + bool FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions); + float GetMonitorSAR(); EGLNativeDisplayType m_display; EGLNativeWindowType m_window; + uint8_t m_edid[512]; }; |