aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjenkins4kodi <jenkins4kodi@users.noreply.github.com>2015-05-01 10:07:00 +0200
committerjenkins4kodi <jenkins4kodi@users.noreply.github.com>2015-05-01 10:07:00 +0200
commit1de18d9d3b75e880b5b12c6858172b145f99771b (patch)
tree2a41dab87d35d5f323bb5acd923594bef61a824a
parent70f4e3f6e201af34c3e455be7e1f38201234132f (diff)
parent31e87e2e6dd21c9d8ea5c7412e4401a114392743 (diff)
Merge pull request #6996 from mk01/master
-rw-r--r--xbmc/windowing/egl/EGLNativeTypeIMX.cpp98
-rw-r--r--xbmc/windowing/egl/EGLNativeTypeIMX.h6
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];
};