00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "LampBasic.h"
00026 #include "Graphics/System/GraphicsDevice.h"
00027 #include "Graphics/System/LampGraphics.h"
00028 #include "Graphics/DeviceSelector/GraphicsDeviceSelector.h"
00029 #include "Graphics/System/GraphicsDeviceSettings.h"
00030 #include "Graphics/Enumeration/GraphicsDeviceInformation.h"
00031
00032 namespace Lamp{
00033
00034
00035 GraphicsDevice* GraphicsDevice::instance_ = NULL;
00036
00037
00038
00039 GraphicsDevice::GraphicsDevice(){
00040 Assert(instance_ == NULL);
00041 instance_ = this;
00042 direct3DDevice_ = NULL;
00043 ::memset(&presentationParameter_, 0, sizeof(D3DPRESENT_PARAMETERS));
00044 settings_ = NULL;
00045 windowHandle_ = NULL;
00046 windowStyle_ = 0;
00047 SetRect(&windowBoundsSize_, 0, 0, 0, 0);
00048 SetRect(&windowClientSize_, 0, 0, 0, 0);
00049 menuHandle_ = NULL;
00050 deviceLost_ = false;
00051 clipCursor_ = true;
00052 ignoreSizeChange_ = false;
00053 windowMaximized_ = false;
00054 windowMinimized_ = false;
00055 }
00056
00057
00058 GraphicsDevice::~GraphicsDevice(){
00059 Assert(instance_ == this);
00060 instance_ = NULL;
00061 }
00062
00063
00064 void GraphicsDevice::clear(Color4c color, float zValue, u_int stencilValue){
00065 u_int clearFlag = D3DCLEAR_TARGET;
00066 if(settings_->getDepthStencilEnabled()){ clearFlag |= D3DCLEAR_ZBUFFER; }
00067 direct3DDevice_->Clear(
00068 0, NULL, clearFlag, color.getARGB(), zValue, stencilValue);
00069 }
00070
00071
00072 bool GraphicsDevice::presentation(){
00073
00074
00075 HRESULT result;
00076
00077 if(deviceLost_){
00078 result = direct3DDevice_->TestCooperativeLevel();
00079 if(DirectXFailed(result)){
00080
00081 if(result == D3DERR_DEVICENOTRESET){
00082 if(settings_->isWindowed()){
00083
00084
00085 LampGraphics::getDeviceSelector()->findBestWindowedMode(
00086 windowHandle_, false, false);
00087 settings_->buildPresentationParameters(
00088 &presentationParameter_, windowHandle_);
00089 }
00090 if(!reset()){
00091 ErrorOut("GraphicsDevice::presentation() reset()");
00092 }
00093 }
00094 }else{
00095
00096 deviceLost_ = false;
00097 }
00098 }else{
00099 result = direct3DDevice_->Present(NULL, NULL, NULL, NULL);
00100
00101 if(result == D3DERR_DEVICELOST){ deviceLost_ = true; }
00102 }
00103 return deviceLost_;
00104 }
00105
00106
00107 void GraphicsDevice::toggleFullscreen(){
00108
00109 GraphicsDeviceInformation* deviceInfoOld =
00110 settings_->getDeviceInformation();
00111 int adapterOrdinalOld = deviceInfoOld->getAdapterOrdinal();
00112 D3DDEVTYPE deviceTypeOld = deviceInfoOld->getDeviceType();
00113
00114 ignoreSizeChange_ = true;
00115
00116 settings_->setWindowed(!settings_->isWindowed());
00117
00118 adjustWindowForChange();
00119
00120 bool result;
00121 GraphicsDeviceInformation* deviceInfo = settings_->getDeviceInformation();
00122 if((deviceInfo->getAdapterOrdinal() == adapterOrdinalOld) &&
00123 (deviceInfo->getDeviceType() == deviceTypeOld)){
00124
00125 settings_->buildPresentationParameters(
00126 &presentationParameter_, windowHandle_);
00127 result = reset();
00128 }else{
00129
00130 result = rebuild();
00131 }
00132
00133 if(!result){ toggleFullscreen(); }
00134
00135 ignoreSizeChange_ = false;
00136 }
00137
00138
00139 void GraphicsDevice::forceWindowed(){
00140 if(settings_->isWindowed()){ return; }
00141 LampGraphics::getDeviceSelector()->findBestWindowedMode(
00142 windowHandle_, false, false);
00143 if(!rebuild()){ ErrorOut("GraphicsDevice::forceWindowed() rebuild()"); }
00144 }
00145
00146
00147 bool GraphicsDevice::rebuild(){
00148 cleanup();
00149 return initialize();
00150 }
00151
00152
00153 void GraphicsDevice::initializeWindowHandle(HWND windowHandle){
00154
00155 windowHandle_ = windowHandle;
00156 windowStyle_ = ::GetWindowLong(windowHandle_, GWL_STYLE);
00157 ::GetWindowRect(windowHandle_, &windowBoundsSize_);
00158 ::GetClientRect(windowHandle_, &windowClientSize_);
00159
00160 settings_ = GraphicsDeviceSettings::getInstance();
00161 }
00162
00163
00164 bool GraphicsDevice::initialize(){
00165
00166 adjustWindowForChange();
00167
00168 settings_->buildPresentationParameters(
00169 &presentationParameter_, windowHandle_);
00170
00171 u_int vertexProsessingFlag =
00172 settings_->getVertexProcessingType().getCreateFlag();
00173
00174 HRESULT result;
00175 Direct3D* direct3D = LampGraphics::getDirect3D();
00176 GraphicsDeviceInformation* deviceInfo = settings_->getDeviceInformation();
00177 result = direct3D->CreateDevice(
00178 deviceInfo->getAdapterOrdinal(),
00179 deviceInfo->getDeviceType(),
00180 windowHandle_,
00181 vertexProsessingFlag,
00182 &presentationParameter_,
00183 &direct3DDevice_);
00184 if(DirectXSucceeded(result)){
00185
00186 LampGraphics::deviceReset();
00187
00188 clipCursor();
00189
00190 if(!LampGraphics::initializeDeviceObjects()){
00191 LampGraphics::deleteDeviceObjects();
00192 }else{
00193 if(!LampGraphics::restoreDeviceObjects()){
00194 LampGraphics::invalidateDeviceObjects();
00195 }else{
00196 return true;
00197 }
00198 }
00199 cleanup();
00200 }
00201
00202 if(deviceInfo->getDeviceType() == D3DDEVTYPE_HAL){
00203 if(LampGraphics::getDeviceSelector()->findBestWindowedMode(
00204 windowHandle_, false, true)){
00205 adjustWindowForChange();
00206 AssertMessage(false, "GraphicsDevice::initialize() "
00207 "Switched to REF");
00208 return initialize();
00209 }
00210 }
00211 return false;
00212
00213 }
00214
00215
00216 bool GraphicsDevice::reset(){
00217
00218 LampGraphics::invalidateDeviceObjects();
00219
00220 direct3DDevice_->Reset(&presentationParameter_);
00221
00222 LampGraphics::deviceReset();
00223
00224 clipCursor();
00225
00226 if(!LampGraphics::restoreDeviceObjects()){
00227 LampGraphics::invalidateDeviceObjects();
00228 return false;
00229 }
00230 return true;
00231 }
00232
00233
00234 void GraphicsDevice::clipCursor(){
00235 if(!clipCursor_){ return; }
00236 if(settings_->isWindowed()){
00237 ClipCursor(NULL);
00238 }else{
00239 RECT clipRect;
00240 GetWindowRect(windowHandle_, &clipRect);
00241 ClipCursor(&clipRect);
00242 }
00243 }
00244
00245
00246 void GraphicsDevice::cleanup(){
00247
00248 LampGraphics::invalidateDeviceObjects();
00249
00250 LampGraphics::deleteDeviceObjects();
00251
00252 SafeRelease(direct3DDevice_);
00253 }
00254
00255
00256 LRESULT GraphicsDevice::windowProcedure(
00257 HWND windowHandle, u_int message, WPARAM wParam, LPARAM lParam){
00258 switch(message){
00259
00260 case WM_SIZE:
00261 if(settings_->isWindowed() && windowHandle_ != NULL){
00262 windowStyle_ = GetWindowLong(windowHandle_, GWL_STYLE);
00263 }
00264 if(wParam == SIZE_MINIMIZED){
00265
00266 if(clipCursor_ && (!settings_->isWindowed())){
00267 ClipCursor(NULL);
00268 }
00269 windowMinimized_ = true;
00270 windowMaximized_ = false;
00271 }else if(wParam == SIZE_MAXIMIZED){
00272 windowMaximized_ = true;
00273 windowMinimized_ = false;
00274 handlePossibleSizeChange();
00275 }else if(wParam == SIZE_RESTORED){
00276 if(windowMaximized_){
00277 windowMaximized_ = false;
00278 handlePossibleSizeChange();
00279 }else if(windowMinimized_){
00280 windowMinimized_ = false;
00281 handlePossibleSizeChange();
00282 }
00283
00284 }
00285 break;
00286
00287 case WM_EXITSIZEMOVE:
00288 handlePossibleSizeChange();
00289 break;
00290
00291 case WM_NCHITTEST:
00292 if(!settings_->isWindowed()){ return HTCLIENT; }
00293 break;
00294
00295 case WM_SYSCOMMAND:
00296 switch(wParam){
00297
00298 case SC_MOVE:
00299 case SC_SIZE:
00300 case SC_MAXIMIZE:
00301 case SC_KEYMENU:
00302 case SC_MONITORPOWER:
00303 if(!settings_->isWindowed()){ return 1; }
00304 break;
00305 }
00306 break;
00307 }
00308 return 0;
00309 }
00310
00311
00312 void GraphicsDevice::adjustWindowForChange(){
00313 if(settings_->isWindowed()){
00314
00315 SetWindowLong(windowHandle_, GWL_STYLE, windowStyle_);
00316
00317 if(menuHandle_ != NULL){
00318 SetMenu(windowHandle_, menuHandle_);
00319 menuHandle_ = NULL;
00320 }
00321
00322 SetWindowPos(windowHandle_, HWND_NOTOPMOST,
00323 windowBoundsSize_.left, windowBoundsSize_.top,
00324 (windowBoundsSize_.right - windowBoundsSize_.left),
00325 (windowBoundsSize_.bottom - windowBoundsSize_.top),
00326 SWP_SHOWWINDOW);
00327 }else{
00328
00329 u_int fullScreenStyle = (WS_POPUP | WS_SYSMENU | WS_VISIBLE);
00330 SetWindowLong(windowHandle_, GWL_STYLE, fullScreenStyle);
00331
00332 if(menuHandle_ == NULL){
00333 menuHandle_ = GetMenu(windowHandle_);
00334 SetMenu(windowHandle_, NULL);
00335 }
00336 }
00337 }
00338
00339
00340 void GraphicsDevice::handlePossibleSizeChange(){
00341
00342 if(ignoreSizeChange_){ return; }
00343
00344 RECT windowClientSizeOld = windowClientSize_;
00345
00346 ::GetWindowRect(windowHandle_, &windowBoundsSize_);
00347 ::GetClientRect(windowHandle_, &windowClientSize_);
00348
00349 int width = (windowClientSize_.right - windowClientSize_.left);
00350 int height = (windowClientSize_.bottom - windowClientSize_.top);
00351 if(((windowClientSizeOld.right - windowClientSizeOld.left) == width) &&
00352 ((windowClientSizeOld.bottom - windowClientSizeOld.top) == height)){
00353 return;
00354 }
00355 settings_->setWindowSize(DimensionI(width, height));
00356 settings_->buildPresentationParameters(
00357 &presentationParameter_, windowHandle_);
00358 if(!reset()){
00359 ErrorOut("GraphicsDevice::handlePossibleSizeChange()");
00360 }
00361
00362 clear();
00363 }
00364
00365 }
00366