Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

DesktopGraphicsDeviceSelector.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 // Lamp : Open source game middleware
00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //------------------------------------------------------------------------------
00019 
00020 /** @file
00021  * デスクトップグラフィックスデバイスセレクタ実装
00022  * @author Junpee
00023  */
00024 
00025 #include "LampBasic.h"
00026 #include "Graphics/DeviceSelector/DesktopGraphicsDeviceSelector.h"
00027 #include "Graphics/System/LampGraphics.h"
00028 #include "Graphics/System/GraphicsDeviceSettings.h"
00029 #include "Graphics/Enumeration/GraphicsDeviceEnumeration.h"
00030 
00031 namespace Lamp{
00032 
00033 //------------------------------------------------------------------------------
00034 // コンストラクタ
00035 DesktopGraphicsDeviceSelector::DesktopGraphicsDeviceSelector(){
00036 }
00037 //------------------------------------------------------------------------------
00038 // デストラクタ
00039 DesktopGraphicsDeviceSelector::~DesktopGraphicsDeviceSelector(){
00040 }
00041 //------------------------------------------------------------------------------
00042 // ウィンドウモードの最適な設定を探す
00043 bool DesktopGraphicsDeviceSelector::findBestWindowedMode(
00044     HWND windowHandle, bool requireHAL, bool requireREF){
00045     Direct3D* direct3D = LampGraphics::getDirect3D();
00046     GraphicsDeviceEnumeration* enumeration =
00047         GraphicsDeviceEnumeration::getInstance();
00048     // 最適なデバイス群
00049     GraphicsAdapterInformation* bestAdapter = NULL;
00050     GraphicsDeviceInformation* bestDevice = NULL;
00051     GraphicsDeviceComboInformation* bestDeviceCombo = NULL;
00052     // ウィンドウはプライマリデスクトップにあると仮定する
00053     D3DDISPLAYMODE primaryDesktopDisplayMode;
00054     direct3D->GetAdapterDisplayMode(0, &primaryDesktopDisplayMode);
00055     // 最適なデバイスを探す
00056     bool foundBestDevice = false;
00057     // アダプタループ
00058     int adapterCount = enumeration->getAdapterCount();
00059     for(int i = 0; i < adapterCount; i++){
00060         GraphicsAdapterInformation* adapter = enumeration->getAdapter(i);
00061         // デバイスループ
00062         int deviceCount = adapter->getDeviceCount();
00063         for(int j = 0; j < deviceCount; j++){
00064             GraphicsDeviceInformation* device = adapter->getDevice(j);
00065             // HAL要求に答えられないなら無視
00066             if(requireHAL && (device->getDeviceType() != D3DDEVTYPE_HAL)){
00067                 continue;
00068             }
00069             // REF要求に答えられないなら無視
00070             if(requireREF && (device->getDeviceType() != D3DDEVTYPE_REF)){
00071                 continue;
00072             }
00073             // デバイスコンボループ
00074             int deviceComboCount = device->getDeviceComboCount();
00075             for(int k = 0; k < deviceComboCount; k++){
00076                 GraphicsDeviceComboInformation* combo =
00077                     device->getDeviceCombo(k);
00078                 // フルスクリーンモードなら無視
00079                 if(!combo->isWindowed()){ continue; }
00080                 // フォーマットが合わなければ無視
00081                 if(combo->getAdapterFormat() !=
00082                     primaryDesktopDisplayMode.Format){ continue; }
00083                 // バックバッファとフォーマット一致
00084                 bool matchedBackBuffer = 
00085                     (combo->getAdapterFormat() == combo->getBackBufferFormat());
00086                 if( // デバイスコンボがNULLなら合格
00087                     (bestDeviceCombo == NULL) ||
00088                     // HALに対応できるようになるなら合格
00089                     ((bestDeviceCombo->getDeviceType() != D3DDEVTYPE_HAL) &&
00090                         (combo->getDeviceType() == D3DDEVTYPE_HAL)) ||
00091                     // HALでバックバッファが一致するなら合格
00092                     ((bestDeviceCombo->getDeviceType() == D3DDEVTYPE_HAL) &&
00093                         matchedBackBuffer)
00094                 ){
00095                     bestAdapter = adapter;
00096                     bestDevice = device;
00097                     bestDeviceCombo = combo;
00098                     // 最高の条件ならループを終了させる
00099                     if((device->getDeviceType() == D3DDEVTYPE_HAL) &&
00100                         matchedBackBuffer){
00101                         foundBestDevice = true;
00102                         break;
00103                     }
00104                 }
00105             }
00106             if(foundBestDevice){ break; }
00107         }
00108         if(foundBestDevice){ break; }
00109     }
00110     // デバイスを発見できなければ失敗
00111     if(bestDeviceCombo == NULL){ return false; }
00112 
00113     // 設定にコピーする
00114     buildWindowModeSettings(windowHandle, primaryDesktopDisplayMode,
00115         bestAdapter, bestDevice, bestDeviceCombo);
00116     return true;
00117 }
00118 //------------------------------------------------------------------------------
00119 // フルスクリーンモードの最適な設定を探す
00120 bool DesktopGraphicsDeviceSelector::findBestFullscreenMode(
00121     HWND windowHandle, bool requireHAL, bool requireREF){
00122     Direct3D* direct3D = LampGraphics::getDirect3D();
00123     GraphicsDeviceEnumeration* enumeration =
00124         GraphicsDeviceEnumeration::getInstance();
00125     // 最適なデバイス群
00126     GraphicsAdapterInformation* bestAdapter = NULL;
00127     GraphicsDeviceInformation* bestDevice = NULL;
00128     GraphicsDeviceComboInformation* bestDeviceCombo = NULL;
00129     // 最適なデスクトップのディスプレイモード
00130     // 現在のデスクトップディスプレイモードに合わそうとします
00131     D3DDISPLAYMODE bestDesktopDisplayMode;
00132     // 最適なデバイスを探す
00133     bool foundBestDevice = false;
00134     // アダプタループ
00135     int adapterCount = enumeration->getAdapterCount();
00136     for(int i = 0; i < adapterCount; i++){
00137         GraphicsAdapterInformation* adapter = enumeration->getAdapter(i);
00138         // アダプタディスプレイモード取得
00139         D3DDISPLAYMODE desktopDisplayMode;
00140         direct3D->GetAdapterDisplayMode(
00141             adapter->getAdapterOrdinal(), &desktopDisplayMode);
00142         // デバイスループ
00143         int deviceCount = adapter->getDeviceCount();
00144         for(int j = 0; j < deviceCount; j++){
00145             GraphicsDeviceInformation* device = adapter->getDevice(j);
00146             // HAL要求に答えられないなら無視
00147             if(requireHAL && (device->getDeviceType() != D3DDEVTYPE_HAL)){
00148                 continue;
00149             }
00150             // REF要求に答えられないなら無視
00151             if(requireREF && (device->getDeviceType() != D3DDEVTYPE_REF)){
00152                 continue;
00153             }
00154             // デバイスコンボループ
00155             int deviceComboCount = device->getDeviceComboCount();
00156             for(int k = 0; k < deviceComboCount; k++){
00157                 GraphicsDeviceComboInformation* combo =
00158                     device->getDeviceCombo(k);
00159                 // ウィンドウモードなら無視
00160                 if(combo->isWindowed()){ continue; }
00161                 // デスクトップとフォーマット一致
00162                 bool matchedDesktop =
00163                     (combo->getAdapterFormat() == desktopDisplayMode.Format);
00164                 // バックバッファとフォーマット一致
00165                 bool matchedBackBuffer = 
00166                     (combo->getAdapterFormat() == combo->getBackBufferFormat());
00167                 // デバイスコンボの審査
00168                 if( // デバイスコンボがNULLなら合格
00169                     (bestDeviceCombo == NULL) ||
00170                     // HALに対応できるようになるなら合格
00171                     ((bestDeviceCombo->getDeviceType() != D3DDEVTYPE_HAL) &&
00172                         (combo->getDeviceType() == D3DDEVTYPE_HAL)) ||
00173                     // HALでデスクトップフォーマットを一致できるようになるなら合格
00174                     ((bestDeviceCombo->getDeviceType() == D3DDEVTYPE_HAL) &&
00175                         (bestDeviceCombo->getAdapterFormat() !=
00176                             desktopDisplayMode.Format) && matchedDesktop) ||
00177                     // HALでデスクトップもバックバッファも一致するなら合格
00178                     ((bestDeviceCombo->getDeviceType() == D3DDEVTYPE_HAL) &&
00179                         matchedDesktop && matchedBackBuffer)
00180                 ){
00181                     // 合格したのでデータ保存
00182                     bestDesktopDisplayMode = desktopDisplayMode;
00183                     bestAdapter = adapter;
00184                     bestDevice = device;
00185                     bestDeviceCombo = combo;
00186                     // 最高の条件ならループを終了させる
00187                     if((device->getDeviceType() == D3DDEVTYPE_HAL) &&
00188                         matchedDesktop && matchedBackBuffer){
00189                         foundBestDevice = true;
00190                         break;
00191                     }
00192                 }
00193             }
00194             if(foundBestDevice){ break; }
00195         }
00196         if(foundBestDevice){ break; }
00197     }
00198     // デバイスを発見できなければ失敗
00199     if(bestDeviceCombo == NULL){ return false; }
00200 /*
00201     // 最適なディスプレイモードを探す
00202     D3DDISPLAYMODE bestDisplayMode;
00203     bestDisplayMode.Width = 0;
00204     bestDisplayMode.Height = 0;
00205     bestDisplayMode.Format = D3DFMT_UNKNOWN;
00206     bestDisplayMode.RefreshRate = 0;
00207     int displayModeCount = bestAdapter->getDisplayModeCount();
00208     for(int i = 0; i < displayModeCount; i++){
00209         D3DDISPLAYMODE displayMode = bestAdapter->getDisplayMode(i);
00210         // フォーマットが違えば無視
00211         if(bestDeviceCombo->getAdapterFormat() != displayMode.Format){
00212             continue;
00213         }
00214         // デスクトップと完全一致したら終了
00215         if((displayMode.Width == bestDesktopDisplayMode.Width) &&
00216             (displayMode.Height == bestDesktopDisplayMode.Height) &&
00217             (displayMode.RefreshRate == bestDesktopDisplayMode.RefreshRate)){
00218             bestDisplayMode = displayMode;
00219             break;
00220         // リフレッシュレートが大きいだけなら合格
00221         }else if((displayMode.Width == bestDesktopDisplayMode.Width) &&
00222             (displayMode.Height == bestDesktopDisplayMode.Height) &&
00223             (displayMode.RefreshRate > bestDesktopDisplayMode.RefreshRate)){
00224             bestDisplayMode = displayMode;
00225         // 幅が同じなら合格
00226         }else if(displayMode.Width == bestDesktopDisplayMode.Width){
00227             bestDisplayMode = displayMode;
00228         // 一つめのディスプレイモードは合格
00229         }else if(bestDisplayMode.Width == 0){
00230             bestDisplayMode = displayMode;
00231         }
00232     }
00233 //*/
00234 //*
00235     // 最適なディスプレイモードを探す
00236     RECT windowRect;
00237     ::GetClientRect(windowHandle, &windowRect);
00238     DimensionI windowSize(windowRect.right - windowRect.left,
00239         windowRect.bottom - windowRect.top);
00240     D3DDISPLAYMODE bestDisplayMode;
00241     bestDisplayMode.Width = 0;
00242     bestDisplayMode.Height = 0;
00243     bestDisplayMode.Format = D3DFMT_UNKNOWN;
00244     bestDisplayMode.RefreshRate = 0;
00245     int displayModeCount = bestAdapter->getDisplayModeCount();
00246     for(int i = 0; i < displayModeCount; i++){
00247         D3DDISPLAYMODE displayMode = bestAdapter->getDisplayMode(i);
00248         // フォーマットが違えば無視
00249         if(bestDeviceCombo->getAdapterFormat() != displayMode.Format){
00250             continue;
00251         }
00252         // 一つめのディスプレイモードは合格
00253         if(bestDisplayMode.Width == 0){
00254             bestDisplayMode = displayMode;
00255             continue;
00256         }
00257         // 幅が遠ければ不合格
00258         int newWidthDist = Math::abs((int)(
00259             (int)windowSize.width - (int)displayMode.Width));
00260         int bestWidthDist = Math::abs((int)(
00261             (int)windowSize.width - (int)bestDisplayMode.Width));
00262         if(newWidthDist > bestWidthDist){ continue; }
00263         // 幅が同じでなければ合格
00264         if(newWidthDist != bestWidthDist){
00265             bestDisplayMode = displayMode;
00266             continue;
00267         }
00268         // 幅が同じ場合、高さが遠ければ不合格
00269         int newHeightDist = Math::abs((int)(
00270             (int)windowSize.height - (int)displayMode.Height));
00271         int bestHeightDist = Math::abs((int)(
00272             (int)windowSize.height - (int)bestDisplayMode.Height));
00273         if(newHeightDist > bestHeightDist){ continue; }
00274         // 幅が同じ場合、高さが同じでなければ合格
00275         if(newHeightDist != bestHeightDist){
00276             bestDisplayMode = displayMode;
00277             continue;
00278         }
00279         // 幅も高さも同じ場合、リフレッシュレートがより違えば不合格
00280         int newRefreshDist = Math::abs((int)(
00281             (int)bestDesktopDisplayMode.RefreshRate -
00282             (int)displayMode.RefreshRate));
00283         int bestRefreshDist = Math::abs((int)(
00284             (int)bestDesktopDisplayMode.RefreshRate -
00285             (int)bestDisplayMode.RefreshRate));
00286         if(newRefreshDist > bestRefreshDist){ continue; }
00287         // そうでなければ合格
00288         bestDisplayMode = displayMode;
00289     }
00290 //*/
00291     // 設定にコピーする
00292     buildFullscreenModeSettings(
00293         bestDisplayMode, bestAdapter, bestDevice, bestDeviceCombo);
00294     return true;
00295 }
00296 //------------------------------------------------------------------------------
00297 } // End of namespace Lamp
00298 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:29 2005 for Lamp by doxygen 1.3.2