BOOL initD3d(HWND hWnd, BOOL fullscreenMode) { D3DPRESENT_PARAMETERS d3d9pp; d3d9 = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface ZeroMemory(&d3d9pp, sizeof(D3DPRESENT_PARAMETERS)); if (fullscreenMode) d3d9pp.Windowed = FALSE; else d3d9pp.Windowed = TRUE; // use 64bit display mode if supported by Gcard, else use 32bit or 16bit if (SUCCEEDED(d3d9->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A16B16G16R16, D3DFMT_A16B16G16R16, FALSE))) { d3d9pp.BackBufferFormat = D3DFMT_A16B16G16R16; MessageBox(hWnd, "Using 64bit color mode (D3DFMT_A16B16G16R16)", "Information", MB_ICONINFORMATION); } else if (SUCCEEDED(d3d9->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, FALSE))) d3d9pp.BackBufferFormat = D3DFMT_X8R8G8B8; else if (SUCCEEDED(d3d9->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_R5G6B5, D3DFMT_R5G6B5, FALSE))) d3d9pp.BackBufferFormat = D3DFMT_R5G6B5; else if (SUCCEEDED(d3d9->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, FALSE))) d3d9pp.BackBufferFormat = D3DFMT_X1R5G5B5; d3d9pp.BackBufferHeight = SCREEN_HEIGHT; d3d9pp.BackBufferWidth = SCREEN_WIDTH; d3d9pp.hDeviceWindow = hWnd; d3d9pp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3d9pp.EnableAutoDepthStencil = TRUE; // automatically run the z-buffer for us d3d9pp.AutoDepthStencilFormat = D3DFMT_D16; // 16-bit pixel format for the z-buffer d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3d9pp, &d3d9dev); if (!initD3dStuff(hWnd)) return FALSE; // init the 3D objects initLightAndMaterial(); // init the lights and objects materials d3d9dev->SetRenderState(D3DRS_LIGHTING, D3DZB_TRUE); // turn off the 3D lighting d3d9dev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer d3d9dev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); // ambient light d3d9dev->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE); // handle normals in scaling // cant get transperacy to work d3d9dev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); d3d9dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); d3d9dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); d3d9dev->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); d3d9dev->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS , TRUE); // antialising //d3d9dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); // antistrophic when scaled up //d3d9dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); // antistrophic when scaled down return TRUE; }
D3DFORMAT FindBackBufferType(bool bWindowed, int iBPP) { HRESULT hr; // If windowed, then bpp is ignored. Use whatever works. vector<D3DFORMAT> vBackBufferFormats; // throw all possibilities in here /* When windowed, add all formats; otherwise add only formats that match dwBPP. */ if( iBPP == 16 || bWindowed ) { vBackBufferFormats.push_back( D3DFMT_R5G6B5 ); vBackBufferFormats.push_back( D3DFMT_X1R5G5B5 ); vBackBufferFormats.push_back( D3DFMT_A1R5G5B5 ); } if( iBPP == 32 || bWindowed ) { #if !defined(XBOX) vBackBufferFormats.push_back( D3DFMT_R8G8B8 ); #endif vBackBufferFormats.push_back( D3DFMT_X8R8G8B8 ); vBackBufferFormats.push_back( D3DFMT_A8R8G8B8 ); } if( !bWindowed && iBPP != 16 && iBPP != 32 ) { GraphicsWindow::Shutdown(); RageException::Throw( "Invalid BPP '%i' specified", iBPP ); } // Test each back buffer format until we find something that works. for( unsigned i=0; i < vBackBufferFormats.size(); i++ ) { D3DFORMAT fmtBackBuffer = vBackBufferFormats[i]; D3DFORMAT fmtDisplay; if( bWindowed ) fmtDisplay = g_DesktopMode.Format; else // Fullscreen fmtDisplay = vBackBufferFormats[i]; LOG->Trace( "Testing format: display %d, back buffer %d, windowed %d...", fmtDisplay, fmtBackBuffer, bWindowed ); hr = g_pd3d->CheckDeviceType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, fmtDisplay, fmtBackBuffer, bWindowed ); if( FAILED(hr) ) continue; // skip // done searching LOG->Trace( "This will work." ); return fmtBackBuffer; } LOG->Trace( "Couldn't find an appropriate back buffer format." ); return D3DFMT_UNKNOWN; }
HRESULT HookIDirect3D9::CheckDeviceType(LPVOID _this, UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) { LOG_API(); return pD3D->CheckDeviceType(Adapter, DevType, AdapterFormat, BackBufferFormat, bWindowed); }
int EnumerateDriver(D3DDEVICEINFO **tabdev) { typedef char devDesc[4]; unsigned int i, j, k; const DWORD dwNumDeviceTypes = 1; devDesc strDeviceDescs[2] = { "HAL", "REF" }; const D3DDEVTYPE DeviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF }; BOOL bHALExists = FALSE; BOOL bHALIsWindowedCompatible = FALSE; BOOL bHALIsDesktopCompatible = FALSE; BOOL bHALIsSampleCompatible = FALSE; g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); D3DDISPLAYMODE modes[100]; D3DFORMAT formats[20]; DWORD dwNumFormats = 0; DWORD dwNumModes = 0; DWORD dwNumAdapterModes = g_pD3D->GetAdapterModeCount(0, D3DFMT_A8R8G8B8); DWORD dwNumDevices; for(i=0; i < dwNumAdapterModes; i++) { // Get the display mode attributes D3DDISPLAYMODE DisplayMode; g_pD3D->EnumAdapterModes(0, D3DFMT_A8R8G8B8, i, &DisplayMode); // Check if the mode already exists (to filter out refresh rates) for(j=0; j<dwNumModes; j++) { if(( modes[j].Width == DisplayMode.Width ) && ( modes[j].Height == DisplayMode.Height ) && ( modes[j].Format == DisplayMode.Format )) break; } // If we found a new mode, add it to the list of modes if (j == dwNumModes) { modes[dwNumModes].Width = DisplayMode.Width; modes[dwNumModes].Height = DisplayMode.Height; modes[dwNumModes].Format = DisplayMode.Format; modes[dwNumModes].RefreshRate = 0; dwNumModes++; // Check if the mode's format already exists for(k=0; k<dwNumFormats; k++) { if (DisplayMode.Format == formats[k]) break; } // If the format is new, add it to the list if(k==dwNumFormats) formats[dwNumFormats++] = DisplayMode.Format; } } // Sort the list of display modes (by format, then width, then height) qsort(modes, dwNumModes, sizeof(D3DDISPLAYMODE), SortModesCallback); // Add devices to adapter dwNumDevices=0; for(i=0; i<dwNumDeviceTypes; i++) { // Fill in device info D3DDEVICEINFO *pDevice; pDevice = &g_Devices[dwNumDevices]; pDevice->DeviceType = DeviceTypes[i]; // se non ci sono devices HAL o T&L ritorna errore if (g_pD3D->GetDeviceCaps(0, D3DDEVTYPE_HAL, &pDevice->d3dCaps)!=D3D_OK) return(-1); strcpy(pDevice->strDesc, strDeviceDescs[i]); pDevice->dwNumModes = 0; pDevice->bCanDoWindowed = FALSE; pDevice->MultiSampleType = D3DMULTISAMPLE_NONE; // Examine each format supported by the adapter to see if it will // work with this device and meets the needs of the application. BOOL bFormatConfirmed[20]; DWORD dwBehavior[20]; D3DFORMAT fmtDepthStencil[20]; for(DWORD f=0; f<dwNumFormats; f++) { bFormatConfirmed[f] = FALSE; fmtDepthStencil[f] = D3DFMT_UNKNOWN; // Skip formats that cannot be used as render targets on this device if( FAILED(g_pD3D->CheckDeviceType(0, pDevice->DeviceType, formats[f], formats[f], FALSE ))) continue; if(pDevice->DeviceType == D3DDEVTYPE_HAL ) { // This system has a HAL device bHALExists = TRUE; if(pDevice->d3dCaps.Caps2) { // HAL can run in a window for some mode bHALIsWindowedCompatible = TRUE; /* if(f == 0) { // HAL can run in a window for the current desktop mode bHALIsDesktopCompatible = TRUE; } */ } } // Confirm the device/format for HW vertex processing if (pDevice->d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { if (pDevice->d3dCaps.DevCaps & D3DDEVCAPS_PUREDEVICE) { dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE; bFormatConfirmed[f] = TRUE; } if (FALSE == bFormatConfirmed[f]) { dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING; bFormatConfirmed[f] = TRUE; } if (FALSE == bFormatConfirmed[f]) { dwBehavior[f] = D3DCREATE_MIXED_VERTEXPROCESSING; bFormatConfirmed[f] = TRUE; } } // Confirm the device/format for SW vertex processing if(bFormatConfirmed[f]==FALSE) { dwBehavior[f] = D3DCREATE_SOFTWARE_VERTEXPROCESSING; bFormatConfirmed[f] = TRUE; } // Find a suitable depth/stencil buffer format for this device/format if(bFormatConfirmed[f]) { if(!FindDepthStencilFormat(0, pDevice->DeviceType, formats[f], &fmtDepthStencil[f])) { bFormatConfirmed[f] = FALSE; } } } // Add all enumerated display modes with confirmed formats to the // device's list of valid modes for(DWORD m=0L; m<dwNumModes; m++) { for( DWORD f=0; f<dwNumFormats; f++) { if (modes[m].Format == formats[f]) { if(bFormatConfirmed[f] == TRUE) { // Add this mode to the device's list of valid modes pDevice->SupportedModes[pDevice->dwNumModes].Width = modes[m].Width; pDevice->SupportedModes[pDevice->dwNumModes].Height = modes[m].Height; pDevice->SupportedModes[pDevice->dwNumModes].Format = modes[m].Format; pDevice->SupportedModes[pDevice->dwNumModes].Bpp = D3DFormat2Bpp(modes[m].Format); pDevice->SupportedModes[pDevice->dwNumModes].dwBehavior = dwBehavior[f]; pDevice->SupportedModes[pDevice->dwNumModes].DepthStencilFormat = fmtDepthStencil[f]; pDevice->dwNumModes++; if(pDevice->DeviceType == D3DDEVTYPE_HAL) bHALIsSampleCompatible = TRUE; } } } } if (pDevice->d3dCaps.Caps2) pDevice->bCanDoWindowed = TRUE; if (pDevice->dwNumModes > 0) dwNumDevices++; } if(0 == dwNumDevices) { *tabdev=NULL; return -1; } else { *tabdev=g_Devices; return(dwNumDevices); } }
BOOL render_init( render_info_t * info ) { HRESULT LastError; render_viewport_t viewport; // should get this from d3d caps bSquareOnly = FALSE; // default gamma table build_gamma_table(1.0); // Set up Direct3D interface object lpD3D = Direct3DCreate9(D3D_SDK_VERSION); if (!lpD3D) { DebugPrintf("couldnt create d3d9\n"); return FALSE; } // create d3d device D3DPRESENT_PARAMETERS d3dpp; ZeroMemory (&d3dpp, sizeof(d3dpp)); // d3dpp.Windowed = !info->fullscreen; // // presentation settings // d3dpp.hDeviceWindow = GetActiveWindow(); // the window handle d3dpp.BackBufferCount = 1; // we only have one swap chain d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // does not protect the contents of the backbuffer after flipping (faster) // shouldn't we specify D3DSWAPEFFECT_FLIP ? // wouldn't D3DSWAPEFFECT_OVERLAY be fastest ? d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // display refresh d3dpp.EnableAutoDepthStencil = TRUE; // let d3d manage the z-buffer if(info->vsync) d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // enable vsync else d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // disable vsync // 16 bit zbuffer //d3dpp.AutoDepthStencilFormat = D3DFMT_D15S1; // 16 bit depth buffer with 1 bit stencil d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 16 bit depth buffer // 32 bit back buffer // Also supports 32 bit zbuffer if( SUCCEEDED(lpD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, d3dpp.Windowed))) { bpp = 32; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; //d3dpp.AutoDepthStencilFormat = D3DFMT_D32; // 32 bit depth buffer d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; // 24 bit depth buffer with 8 bit stencil buffer DebugPrintf("picked 24 bit D3DFMT_X8R8G8B8 back buffer\n"); } // 16 bit else if(SUCCEEDED(lpD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, d3dpp.Windowed))) { d3dpp.BackBufferFormat = D3DFMT_X1R5G5B5; DebugPrintf("picked 16 bit D3DFMT_X1R5G5B5 back buffer\n"); } // 16 bit else if(SUCCEEDED(lpD3D->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_R5G6B5, D3DFMT_R5G6B5, d3dpp.Windowed))) { d3dpp.BackBufferFormat = D3DFMT_R5G6B5; DebugPrintf("picked 16 bit D3DFMT_R5G6B5 back buffer\n"); } // failed else { CloseWindow(d3dpp.hDeviceWindow); Msg("Failed to find a suitable back buffer format"); exit(1); } // // Enumerates display modes // picking info->default_mode if it exists // or picking the biggest mode possible :] // #if 0 // done by sdl now { int mode = 0; int desired_mode = -1; int best_mode = 0; // default to the first mode int i; int x = 0; int count = (int) lpD3D->GetAdapterModeCount( D3DADAPTER_DEFAULT, d3dpp.BackBufferFormat ); info->Mode = (render_display_mode_t *) malloc( count * sizeof(render_display_mode_t) ); D3DDISPLAYMODE * modes = (D3DDISPLAYMODE *) malloc( count * sizeof(D3DDISPLAYMODE) ); for ( i = 0; i < count; i++ ) { // get the mode description lpD3D->EnumAdapterModes( D3DADAPTER_DEFAULT, d3dpp.BackBufferFormat, i, &modes[i] ); DebugPrintf("Enumerated mode: %dx%d @ %dhz , format=%d\n", modes[i].Width,modes[i].Height,modes[i].RefreshRate,modes[i].Format); // ignore modes under 640x480 if(modes[i].Width < 640 || modes[i].Height < 480) { DebugPrintf("Skipping mode because it's to small for anyone to want...\n"); continue; } // save the mode info->Mode[x].h = modes[i].Height; info->Mode[x].w = modes[i].Width; info->Mode[x].bpp = bpp; // if this is the mode the user wanted pick it if( info->Mode[x].w == info->default_mode.w && info->Mode[x].h == info->default_mode.h ) { desired_mode = x; } // smallest mode as default if( info->Mode[x].w < info->Mode[best_mode].w && info->Mode[x].h < info->Mode[best_mode].h ) { best_mode = x; } // biggest mode by width as default //if(info->Mode[x].w > info->Mode[best_mode].w ) // best_mode = x; // 800x600 @ 60 as default //if( info->Mode[x].w == 800 && info->Mode[x].h == 600 ) // desired_mode = x; // go to next storage location x++; } info->NumModes = x; if( desired_mode >= 0 ) { mode = desired_mode; } else { mode = best_mode; } info->CurrMode = mode; info->ThisMode = info->Mode[ info->CurrMode ]; info->WindowsDisplay = info->Mode[ info->CurrMode ]; info->window_size.cx = info->ThisMode.w; info->window_size.cy = info->ThisMode.h; info->WindowsDisplay.w = info->ThisMode.w; info->WindowsDisplay.h = info->ThisMode.h; free(modes); } #endif // done by sdl now d3dpp.BackBufferWidth = info->ThisMode.w; d3dpp.BackBufferHeight = info->ThisMode.h; info->aspect_ratio = (float) info->ThisMode.w / (float) info->ThisMode.h; DebugPrintf("Using display mode: %dx%d\n", info->ThisMode.w,info->ThisMode.h); // try to create a device falling back to less capable versions // // TODO // the docs say that pure devices don't support Get* calls // which explains why people are crashing on FSGet* functions for no reason // to support pure device we'd have to track our own states // /* LastError = lpD3D->CreateDevice( D3DADAPTER_DEFAULT, // the default video card D3DDEVTYPE_HAL, // device type - hal = Hardware rasterization d3dpp.hDeviceWindow, // the window handle // these define how the device is created D3DCREATE_HARDWARE_VERTEXPROCESSING | // do vertex processing in hardware D3DCREATE_PUREDEVICE, // D3D will not support Get* calls for anything that can be stored in state blocks. // and not to provide any emulation services for vertex processing. // Thus if the device does not support vertex processing, // then the application can use only post-transformed vertices. &d3dpp, // presentation parameters defined above &lpD3DDevice // pointer that will contain the returned device ); if (SUCCEEDED(LastError)) { Msg("pure"); } if (FAILED(LastError)) */ { LastError = lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &lpD3DDevice); if (SUCCEEDED(LastError)) { DebugPrintf("d3d device created: hardware\n"); } else { const char * error = render_error_description(LastError); DebugPrintf("d3d device create failed with hardware: %s\n",error); } } if (FAILED(LastError)) { LastError = lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_MIXED_VERTEXPROCESSING, // do vertex processing in both hardware and software &d3dpp, &lpD3DDevice); if (SUCCEEDED(LastError)) { DebugPrintf("d3d device created: mixed\n"); } else { const char * error = render_error_description(LastError); DebugPrintf("d3d device create failed with mixed: %s\n",error); } } if (FAILED(LastError)) { LastError = lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, // do vertex processing in software only &d3dpp, &lpD3DDevice); if (SUCCEEDED(LastError)) { DebugPrintf("d3d device created: software\n"); } else { const char * error = render_error_description(LastError); DebugPrintf("d3d device create failed with software: %s\n",error); } } if (FAILED(LastError)) { CloseWindow(d3dpp.hDeviceWindow); Msg("Failed to create a suitable d3d device:\n%s", render_error_description(LastError)); exit(1); } info->ok_to_render = TRUE; viewport.X = 0; viewport.Y = 0; /* do "after device created" stuff */ ZeroMemory( &viewport, sizeof(viewport) ); { WINDOWPLACEMENT placement; placement.length = sizeof(WINDOWPLACEMENT); if(GetWindowPlacement( d3dpp.hDeviceWindow, &placement )) { viewport.X = placement.rcNormalPosition.left; viewport.Y = placement.rcNormalPosition.top; } } viewport.Width = d3dpp.BackBufferWidth; viewport.Height = d3dpp.BackBufferHeight; viewport.MinZ = 0.0f; viewport.MaxZ = 1.0f; LastError = FSSetViewPort(&viewport); if (!LastError) { DebugPrintf("couldn't set viewport\n"); } if(!init_render_states( info )) return FALSE; return TRUE; }