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 //------------------------------------------------------------------------------