OVR_OSX_HMDDevice.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   OVR_OSX_HMDDevice.cpp
00004 Content     :   OSX Interface to HMD - detects HMD display
00005 Created     :   September 21, 2012
00006 Authors     :   Michael Antonov
00007 
00008 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00009 
00010 Use of this software is subject to the terms of the Oculus license
00011 agreement provided at the time of installation or download, or which
00012 otherwise accompanies this software in either electronic or hard copy form.
00013 
00014 *************************************************************************************/
00015 
00016 #include "OVR_OSX_HMDDevice.h"
00017 #include <CoreGraphics/CGDirectDisplay.h>
00018 #include <CoreGraphics/CGDisplayConfiguration.h>
00019 #include <CoreFoundation/CoreFoundation.h>
00020 #include <CoreFoundation/CFString.h>
00021 #include <IOKit/graphics/IOGraphicsLib.h>
00022 
00023 namespace OVR { namespace OSX {
00024 
00025 //-------------------------------------------------------------------------------------
00026 
00027 HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, 
00028                                          UInt32 vend, UInt32 prod, const String& displayDeviceName, long dispId)
00029         : DeviceCreateDesc(factory, Device_HMD),
00030           DisplayDeviceName(displayDeviceName),
00031           DesktopX(0), DesktopY(0), Contents(0),
00032           HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
00033           DisplayId(dispId)
00034 {
00035     /* //??????????
00036     char idstring[9];
00037     idstring[0] = 'A'-1+((vend>>10) & 31);
00038     idstring[1] = 'A'-1+((vend>>5) & 31);
00039     idstring[2] = 'A'-1+((vend>>0) & 31);
00040     snprintf(idstring+3, 5, "%04d", prod);
00041     DeviceId = idstring;*/
00042     DeviceId = DisplayDeviceName;
00043 }
00044 
00045 HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
00046         : DeviceCreateDesc(other.pFactory, Device_HMD),
00047           DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
00048           DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents),
00049           HResolution(other.HResolution), VResolution(other.VResolution),
00050           HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize),
00051           DisplayId(other.DisplayId)
00052 {
00053 }
00054 
00055 HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
00056                                                                   DeviceCreateDesc** pcandidate) const
00057 {
00058     if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
00059         return Match_None;
00060 
00061     // There are several reasons we can come in here:
00062     //   a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
00063     //          - Require exact device DeviceId/DeviceName match
00064     //   b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
00065     //          - This DeviceId is empty; becomes candidate
00066     //   c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
00067     //          - This other.DeviceId is empty; becomes candidate
00068 
00069     const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
00070 
00071     if ((DeviceId == s2.DeviceId) &&
00072         (DisplayId == s2.DisplayId))
00073     {
00074         // Non-null DeviceId may match while size is different if screen size was overwritten
00075         // by SensorDisplayInfo in prior iteration.
00076         if (!DeviceId.IsEmpty() ||
00077              ((HScreenSize == s2.HScreenSize) &&
00078               (VScreenSize == s2.VScreenSize)) )
00079         {            
00080             *pcandidate = 0;
00081             return Match_Found;
00082         }
00083     }
00084 
00085 
00086     // DisplayInfo takes precedence, although we try to match it first.
00087     if ((HResolution == s2.HResolution) &&
00088         (VResolution == s2.VResolution) &&
00089         (HScreenSize == s2.HScreenSize) &&
00090         (VScreenSize == s2.VScreenSize))
00091     {
00092         if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
00093         {
00094             *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
00095             return Match_Candidate;
00096         }
00097 
00098         *pcandidate = 0;
00099         return Match_Found;
00100     }    
00101     
00102     // SensorDisplayInfo may override resolution settings, so store as candidiate.
00103     if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
00104     {        
00105         *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);        
00106         return Match_Candidate;
00107     }
00108     // OTHER HMD Monitor desc may initialize DeviceName/Id
00109     else if (DeviceId.IsEmpty() && DisplayId == 0)
00110     {
00111         *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);        
00112         return Match_Candidate;
00113     }
00114     
00115     return Match_None;
00116 }
00117 
00118 
00119 bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, bool* newDeviceFlag)
00120 {
00121     // This candidate was the the "best fit" to apply sensor DisplayInfo to.
00122     OVR_ASSERT(other.Type == Device_HMD);
00123     
00124     const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
00125 
00126     // Force screen size on resolution from SensorDisplayInfo.
00127     // We do this because USB detection is more reliable as compared to HDMI EDID,
00128     // which may be corrupted by splitter reporting wrong monitor 
00129     if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
00130     {
00131         // disconnected HMD: replace old descriptor by the 'fake' one.
00132         HScreenSize = s2.HScreenSize;
00133         VScreenSize = s2.VScreenSize;
00134         Contents |= Contents_Screen;
00135 
00136         if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
00137         {
00138             memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
00139             Contents |= Contents_Distortion;
00140         }
00141         DeviceId          = s2.DeviceId;
00142         DisplayId         = s2.DisplayId;
00143         DisplayDeviceName = s2.DisplayDeviceName;
00144         if (newDeviceFlag) *newDeviceFlag = true;
00145     }
00146     else if (DeviceId.IsEmpty())
00147     {
00148         // This branch is executed when 'fake' HMD descriptor is being replaced by
00149         // the real one.
00150         DeviceId          = s2.DeviceId;
00151         DisplayId         = s2.DisplayId;
00152         DisplayDeviceName = s2.DisplayDeviceName;
00153         if (newDeviceFlag) *newDeviceFlag = true;
00154     }
00155     else
00156     {
00157         if (newDeviceFlag) *newDeviceFlag = false;
00158     }
00159 
00160     return true;
00161 }
00162 
00163     
00164 //-------------------------------------------------------------------------------------
00165 
00166 
00167 //-------------------------------------------------------------------------------------
00168 // ***** HMDDeviceFactory
00169 
00170 HMDDeviceFactory HMDDeviceFactory::Instance;
00171 
00172 void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
00173 {
00174     CGDirectDisplayID Displays[32];
00175     uint32_t NDisplays = 0;
00176     CGGetOnlineDisplayList(32, Displays, &NDisplays);
00177 
00178     for (int i = 0; i < NDisplays; i++)
00179     {
00180         io_service_t port = CGDisplayIOServicePort(Displays[i]);
00181         CFDictionaryRef DispInfo = IODisplayCreateInfoDictionary(port, kIODisplayMatchingInfo);
00182 
00183         uint32_t vendor = CGDisplayVendorNumber(Displays[i]);
00184         uint32_t product = CGDisplayModelNumber(Displays[i]);
00185         unsigned mwidth = (unsigned)CGDisplayPixelsWide(Displays[i]);
00186         unsigned mheight = (unsigned)CGDisplayPixelsHigh(Displays[i]);
00187         CGRect desktop = CGDisplayBounds(Displays[i]);
00188         
00189         if (vendor == 16082 && product == 1)
00190         {
00191             char idstring[9];
00192             idstring[0] = 'A'-1+((vendor>>10) & 31);
00193             idstring[1] = 'A'-1+((vendor>>5) & 31);
00194             idstring[2] = 'A'-1+((vendor>>0) & 31);
00195             snprintf(idstring+3, 5, "%04d", product);
00196 
00197             HMDDeviceCreateDesc hmdCreateDesc(this, vendor, product, idstring, Displays[i]);
00198             
00199                         if (product == 2)
00200                         {
00201                 hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
00202                                                   mwidth, mheight, 0.12096f, 0.06804f);
00203                         }
00204                         else
00205                         {
00206                                 if (hmdCreateDesc.Is7Inch())
00207                                 {
00208                                         // Physical dimension of SLA screen.
00209                                         hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
00210                                                       mwidth, mheight, 0.14976f, 0.0936f);
00211                                 }
00212                                 else
00213                                 {
00214                                         hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
00215                                                       mwidth, mheight, 0.12096f, 0.0756f);
00216                                 }
00217                         }
00218 
00219             OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %x:%x\n", vendor, product));
00220             
00221             // Notify caller about detected device. This will call EnumerateAddDevice
00222             // if the this is the first time device was detected.
00223             visitor.Visit(hmdCreateDesc);
00224         }
00225         CFRelease(DispInfo);
00226     }
00227 }
00228 
00229 DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
00230 {
00231     return new HMDDevice(this);
00232 }
00233 
00234 bool HMDDeviceCreateDesc::Is7Inch() const
00235 {
00236     return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch);
00237 }
00238 
00239 Profile* HMDDeviceCreateDesc::GetProfileAddRef() const
00240 {
00241     // Create device may override profile name, so get it from there is possible.
00242     ProfileManager* profileManager = GetManagerImpl()->GetProfileManager();
00243     ProfileType     profileType    = GetProfileType();
00244     const char *    profileName    = pDevice ?
00245                         ((HMDDevice*)pDevice)->GetProfileName() :
00246                         profileManager->GetDefaultProfileName(profileType);
00247 
00248     return profileName ?
00249         profileManager->LoadProfile(profileType, profileName) :
00250         profileManager->GetDeviceDefaultProfile(profileType);
00251 }
00252 
00253 bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
00254 {
00255     if ((info->InfoClassType != Device_HMD) &&
00256         (info->InfoClassType != Device_None))
00257         return false;
00258 
00259     bool is7Inch = Is7Inch();
00260 
00261     OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength,
00262                is7Inch ? "Oculus Rift DK1" :
00263                            ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") );
00264     OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR");
00265     info->Type    = Device_HMD;
00266     info->Version = 0;
00267 
00268     // Display detection.
00269     if (info->InfoClassType == Device_HMD)
00270     {
00271         HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
00272 
00273         hmdInfo->DesktopX               = DesktopX;
00274         hmdInfo->DesktopY               = DesktopY;
00275         hmdInfo->HResolution            = HResolution;
00276         hmdInfo->VResolution            = VResolution;
00277         hmdInfo->HScreenSize            = HScreenSize;
00278         hmdInfo->VScreenSize            = VScreenSize;
00279         hmdInfo->VScreenCenter          = VScreenSize * 0.5f;
00280         hmdInfo->InterpupillaryDistance = 0.064f;  // Default IPD; should be configurable.
00281         hmdInfo->LensSeparationDistance = 0.0635f;
00282 
00283         // Obtain IPD from profile.
00284         Ptr<Profile> profile = *GetProfileAddRef();
00285 
00286         if (profile)
00287         {
00288             hmdInfo->InterpupillaryDistance = profile->GetIPD();
00289             // TBD: Switch on EyeCup type.
00290         }
00291         
00292         if (Contents & Contents_Distortion)
00293         {
00294             memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4);
00295         }
00296         else
00297         {
00298             if (is7Inch)
00299             {
00300                 // 7" screen.
00301                 hmdInfo->DistortionK[0]        = 1.0f;
00302                 hmdInfo->DistortionK[1]        = 0.22f;
00303                 hmdInfo->DistortionK[2]        = 0.24f;
00304                 hmdInfo->EyeToScreenDistance   = 0.041f;                
00305             }
00306             else
00307             {
00308                 hmdInfo->DistortionK[0]        = 1.0f;
00309                 hmdInfo->DistortionK[1]        = 0.18f;
00310                 hmdInfo->DistortionK[2]        = 0.115f;
00311 
00312                 if (HResolution == 1920)
00313                     hmdInfo->EyeToScreenDistance = 0.040f;
00314                 else
00315                     hmdInfo->EyeToScreenDistance = 0.0387f;
00316             }
00317 
00318             hmdInfo->ChromaAbCorrection[0] = 0.996f;
00319             hmdInfo->ChromaAbCorrection[1] = -0.004f;
00320             hmdInfo->ChromaAbCorrection[2] = 1.014f;
00321             hmdInfo->ChromaAbCorrection[3] = 0.0f;
00322         }
00323 
00324         OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
00325                    DisplayDeviceName.ToCStr());
00326         hmdInfo->DisplayId = DisplayId;
00327     }
00328 
00329     return true;
00330 }
00331 
00332 //-------------------------------------------------------------------------------------
00333 // ***** HMDDevice
00334 
00335 HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
00336     : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
00337 {
00338 }
00339 HMDDevice::~HMDDevice()
00340 {
00341 }
00342 
00343 bool HMDDevice::Initialize(DeviceBase* parent)
00344 {
00345     pParent = parent;
00346 
00347     // Initialize user profile to default for device.
00348     ProfileManager* profileManager = GetManager()->GetProfileManager();    
00349     ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType());
00350 
00351     return true;
00352 }
00353 void HMDDevice::Shutdown()
00354 {
00355     ProfileName.Clear();
00356     pCachedProfile.Clear();
00357     pParent.Clear();
00358 }
00359 
00360 Profile* HMDDevice::GetProfile() const
00361 {    
00362     if (!pCachedProfile)
00363         pCachedProfile = *getDesc()->GetProfileAddRef();
00364     return pCachedProfile.GetPtr();
00365 }
00366 
00367 const char* HMDDevice::GetProfileName() const
00368 {
00369     return ProfileName.ToCStr();
00370 }
00371 
00372 bool HMDDevice::SetProfileName(const char* name)
00373 {
00374     pCachedProfile.Clear();
00375     if (!name)
00376     {
00377         ProfileName.Clear();
00378         return 0;
00379     }
00380     if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name))
00381     {
00382         ProfileName = name;
00383         return true;
00384     }
00385     return false;
00386 }
00387 
00388 OVR::SensorDevice* HMDDevice::GetSensor()
00389 {
00390     // Just return first sensor found since we have no way to match it yet.
00391     OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
00392     if (sensor)
00393         sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
00394     return sensor;
00395 }
00396 
00397 
00398 }} // namespace OVR::OSX
00399 
00400 


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19