BOOL gldCreateDrawable_DX( DGL_ctx *ctx, // BOOL bDefaultDriver, BOOL bDirectDrawPersistant, BOOL bPersistantBuffers) { // // bDirectDrawPersistant: applies to IDirect3D8 // bPersistantBuffers: applies to IDirect3DDevice8 // HRESULT hResult; GLD_driver_dx8 *lpCtx = NULL; D3DDEVTYPE d3dDevType; D3DPRESENT_PARAMETERS d3dpp; D3DDISPLAYMODE d3ddm; DWORD dwBehaviourFlags; D3DADAPTER_IDENTIFIER8 d3dIdent; // Error if context is NULL. if (ctx == NULL) return FALSE; if (ctx->glPriv) { lpCtx = ctx->glPriv; // Release any existing interfaces SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); } else { lpCtx = (GLD_driver_dx8*)malloc(sizeof(GLD_driver_dx8)); ZeroMemory(lpCtx, sizeof(lpCtx)); } d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; // TODO: Check this // if (bDefaultDriver) // d3dDevType = D3DDEVTYPE_REF; // Use persistant interface if needed if (bDirectDrawPersistant && dx8Globals.bDirect3D) { lpCtx->pD3D = dx8Globals.pD3D; IDirect3D8_AddRef(lpCtx->pD3D); goto SkipDirectDrawCreate; } // Create Direct3D8 object lpCtx->pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); if (lpCtx->pD3D == NULL) { MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); nContextError = GLDERR_D3D; goto return_with_error; } // Cache Direct3D interface for subsequent GLRCs if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { dx8Globals.pD3D = lpCtx->pD3D; IDirect3D8_AddRef(dx8Globals.pD3D); dx8Globals.bDirect3D = TRUE; } SkipDirectDrawCreate: // Get the display mode so we can make a compatible backbuffer hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); if (FAILED(hResult)) { nContextError = GLDERR_D3D; goto return_with_error; } // Get device caps hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } // Check for hardware transform & lighting lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; // If this flag is present then we can't default to Mesa // SW rendering between BeginScene() and EndScene(). if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { ddlogMessage(DDLOG_WARN, "Warning : No 2D allowed during 3D scene.\n"); } // // Create the Direct3D context // // Re-use original IDirect3DDevice if persistant buffers exist. // Note that we test for persistant IDirect3D8 as well // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D && dx8Globals.pDev) { lpCtx->pDev = dx8Globals.pDev; IDirect3DDevice8_AddRef(dx8Globals.pDev); goto skip_direct3ddevice_create; } // Clear the presentation parameters (sets all members to zero) ZeroMemory(&d3dpp, sizeof(d3dpp)); // Recommended by MS; needed for MultiSample. // Be careful if altering this for FullScreenBlit d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; if (ctx->bFullscreen) { ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // Support for vertical retrace synchronisation. // Set default presentation interval in case caps bits are missing d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; if (glb.bWaitForRetrace) { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } } else { ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = ctx->dwWidth; d3dpp.BackBufferHeight = ctx->dwHeight; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = 0; // FullScreen_PresentationInterval must be default for Windowed mode d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } // Decide if we can use hardware TnL dwBehaviourFlags = (lpCtx->bHasHWTnL) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Add flag to tell D3D to be thread-safe if (glb.bMultiThreaded) dwBehaviourFlags |= D3DCREATE_MULTITHREADED; // Add flag to tell D3D to be FPU-safe if (!glb.bFastFPU) dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE; hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, glb.dwAdapter, d3dDevType, ctx->hWnd, dwBehaviourFlags, &d3dpp, &lpCtx->pDev); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D) { dx8Globals.pDev = lpCtx->pDev; dx8Globals.bDirect3DDevice = TRUE; } /* // See if DDraw interfaces are available (DaveM) hResult = IDirect3D8_QueryInterface(lpCtx->pDev, &IID_IDirectDraw7, (LPVOID*)&lpOpaque1); if (FAILED(hResult) || lpOpaque1 == NULL) { ddlogMessage(DDLOG_INFO, "DirectDraw QueryInterface unavailable\n"); } hResult = IDirect3DDevice8_QueryInterface(lpCtx->pDev, &IID_IDirectDrawSurface7, (LPVOID*)&lpOpaque2); if (FAILED(hResult) || lpOpaque2 == NULL) { ddlogMessage(DDLOG_INFO, "DirectDrawSurface QueryInterface unavialable\n"); } */ // Dump some useful stats hResult = IDirect3D8_GetAdapterIdentifier( lpCtx->pD3D, glb.dwAdapter, D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay &d3dIdent); if (SUCCEEDED(hResult)) { ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", d3dIdent.Driver, HIWORD(d3dIdent.DriverVersion.HighPart), LOWORD(d3dIdent.DriverVersion.HighPart), HIWORD(d3dIdent.DriverVersion.LowPart), LOWORD(d3dIdent.DriverVersion.LowPart)); ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); } // Init projection matrix for D3D TnL D3DXMatrixIdentity(&lpCtx->matProjection); lpCtx->matModelView = lpCtx->matProjection; // gld->bUseMesaProjection = TRUE; skip_direct3ddevice_create: // Create buffers to hold primitives lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); if (FAILED(hResult)) goto return_with_error; lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); if (FAILED(hResult)) goto return_with_error; /* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders) lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX; lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT; lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX); lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY; hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight); if (FAILED(hResult)) goto return_with_error;*/ // Now try and create the DX8 Vertex Shaders // _gldCreateVertexShaders(lpCtx); // Zero the pipeline usage counters lpCtx->PipelineUsage.qwMesa.QuadPart = // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; // Assign drawable to GL private ctx->glPriv = lpCtx; return TRUE; return_with_error: // Clean up and bail // _gldDestroyVertexShaders(lpCtx); // _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); return FALSE; }
BOOL gldCreateDrawable_DX( DGL_ctx *ctx, // BOOL bDefaultDriver, BOOL bDirectDrawPersistant, BOOL bPersistantBuffers) { // // bDirectDrawPersistant: applies to IDirect3D8 // bPersistantBuffers: applies to IDirect3DDevice8 // // D3DDEVTYPE d3dDevType; // D3DPRESENT_PARAMETERS d3dpp; // D3DDISPLAYMODE d3ddm; // DWORD dwBehaviourFlags; // D3DADAPTER_IDENTIFIER8 d3dIdent; HRESULT hr; GLD_driver_dx7 *lpCtx = NULL; D3DX_VIDMODEDESC d3ddm; // Parameters for D3DXCreateContextEx // These will be different for fullscreen and windowed DWORD dwDeviceIndex; DWORD dwFlags; HWND hwnd; HWND hwndFocus; DWORD numColorBits; DWORD numAlphaBits; DWORD numDepthBits; DWORD numStencilBits; DWORD numBackBuffers; DWORD dwWidth; DWORD dwHeight; DWORD refreshRate; // Error if context is NULL. if (ctx == NULL) return FALSE; if (ctx->glPriv) { lpCtx = ctx->glPriv; // Release any existing interfaces (in reverse order) SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); lpCtx->pD3DXContext = NULL; } else { lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7)); ZeroMemory(lpCtx, sizeof(lpCtx)); } // d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level // of HW acceleration. dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT; // TODO: Check this // if (bDefaultDriver) // d3dDevType = D3DDEVTYPE_REF; #ifdef _GLD_PERSISTANT // Use persistant interface if needed if (bDirectDrawPersistant && dx7Globals.bDirect3D) { lpCtx->pD3D = dx7Globals.pD3D; IDirect3D7_AddRef(lpCtx->pD3D); goto SkipDirectDrawCreate; } #endif /* // Create Direct3D7 object lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); if (lpCtx->pD3D == NULL) { MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); nContextError = GLDERR_D3D; goto return_with_error; } */ #ifdef _GLD_PERSISTANT // Cache Direct3D interface for subsequent GLRCs if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { dx7Globals.pD3D = lpCtx->pD3D; IDirect3D7_AddRef(dx7Globals.pD3D); dx7Globals.bDirect3D = TRUE; } SkipDirectDrawCreate: #endif /* // Get the display mode so we can make a compatible backbuffer hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); if (FAILED(hResult)) { nContextError = GLDERR_D3D; goto return_with_error; } */ #if 0 // Get device caps hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } // Check for hardware transform & lighting lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; // If this flag is present then we can't default to Mesa // SW rendering between BeginScene() and EndScene(). if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { ddlogMessage(DDLOG_WARN, "Warning : No 2D allowed during 3D scene.\n"); } #endif // // Create the Direct3D context // #ifdef _GLD_PERSISTANT // Re-use original IDirect3DDevice if persistant buffers exist. // Note that we test for persistant IDirect3D8 as well // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D && dx7Globals.pDev) { lpCtx->pDev = dx7Globals.pDev; IDirect3DDevice7_AddRef(dx7Globals.pDev); goto skip_direct3ddevice_create; } #endif /* // Clear the presentation parameters (sets all members to zero) ZeroMemory(&d3dpp, sizeof(d3dpp)); // Recommended by MS; needed for MultiSample. // Be careful if altering this for FullScreenBlit d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; if (ctx->bFullscreen) { ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen d3dpp.Windowed = FALSE; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; // Support for vertical retrace synchronisation. // Set default presentation interval in case caps bits are missing d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; if (glb.bWaitForRetrace) { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } } else { ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = ctx->dwWidth; d3dpp.BackBufferHeight = ctx->dwHeight; d3dpp.hDeviceWindow = ctx->hWnd; d3dpp.FullScreen_RefreshRateInHz = 0; // FullScreen_PresentationInterval must be default for Windowed mode d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } // Decide if we can use hardware TnL dwBehaviourFlags = (lpCtx->bHasHWTnL) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Add flag to tell D3D to be thread-safe if (glb.bMultiThreaded) dwBehaviourFlags |= D3DCREATE_MULTITHREADED; hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, glb.dwAdapter, d3dDevType, ctx->hWnd, dwBehaviourFlags, &d3dpp, &lpCtx->pDev); if (FAILED(hResult)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); nContextError = GLDERR_D3D; goto return_with_error; } */ // Create D3DX context if (ctx->bFullscreen) { // // FULLSCREEN // // Get display mode D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); // Fullscreen Parameters dwFlags = D3DX_CONTEXT_FULLSCREEN; hwnd = ctx->hWnd; hwndFocus = ctx->hWnd; numColorBits = ctx->lpPF->pfd.cColorBits; numAlphaBits = ctx->lpPF->pfd.cAlphaBits; numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; numStencilBits = ctx->lpPF->pfd.cStencilBits; numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer dwWidth = d3ddm.width; dwHeight = d3ddm.height; refreshRate = d3ddm.refreshRate; // D3DX_DEFAULT; } else { // // WINDOWED // // Windowed Parameters dwFlags = 0; // No flags means "windowed" hwnd = ctx->hWnd; hwndFocus = (HWND)D3DX_DEFAULT; numColorBits = D3DX_DEFAULT; // Use Desktop depth numAlphaBits = ctx->lpPF->pfd.cAlphaBits; numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; numStencilBits = ctx->lpPF->pfd.cStencilBits; numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer dwWidth = ctx->dwWidth; dwHeight = ctx->dwHeight; refreshRate = D3DX_DEFAULT; } hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus, numColorBits, numAlphaBits, numDepthBits, numStencilBits, numBackBuffers, dwWidth, dwHeight, refreshRate, &lpCtx->pD3DXContext); if (FAILED(hr)) { ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr); nContextError = GLDERR_D3D; goto return_with_error; } // Obtain D3D7 interfaces from ID3DXContext // lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext); lpCtx->pDD = lpCtx->pD3DXContext->lpVtbl->GetDD(lpCtx->pD3DXContext); if (lpCtx->pDD == NULL) goto return_with_error; lpCtx->pD3D = lpCtx->pD3DXContext->lpVtbl->GetD3D(lpCtx->pD3DXContext); if (lpCtx->pD3D == NULL) goto return_with_error; lpCtx->pDev = lpCtx->pD3DXContext->lpVtbl->GetD3DDevice(lpCtx->pD3DXContext); if (lpCtx->pDev == NULL) goto return_with_error; // Need to manage clipper manually for multiple windows // since DX7 D3DX utility lib does not appear to do that. (DaveM) if (!ctx->bFullscreen) { // Get primary surface too lpDDSPrimary = lpCtx->pD3DXContext->lpVtbl->GetPrimary(lpCtx->pD3DXContext); if (lpDDSPrimary == NULL) { ddlogPrintf(DDLOG_WARN, "GetPrimary"); goto return_with_error; } // Create clipper for correct window updates if (IDirectDraw7_CreateClipper(lpCtx->pDD, 0, &lpDDClipper, NULL) != DD_OK) { ddlogPrintf(DDLOG_WARN, "CreateClipper"); goto return_with_error; } // Set the window that the clipper belongs to if (IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hwnd) != DD_OK) { ddlogPrintf(DDLOG_WARN, "SetHWnd"); goto return_with_error; } // Attach the clipper to the primary surface if (IDirectDrawSurface7_SetClipper(lpDDSPrimary, lpDDClipper) != DD_OK) { ddlogPrintf(DDLOG_WARN, "SetClipper"); goto return_with_error; } } // Get device caps IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps); // Determine HW TnL lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; #ifdef _GLD_PERSISTANT if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) { dx7Globals.pDev = lpCtx->pDev; dx7Globals.bDirect3DDevice = TRUE; } #endif #if 0 // Dump some useful stats hResult = IDirect3D8_GetAdapterIdentifier( lpCtx->pD3D, glb.dwAdapter, D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay &d3dIdent); if (SUCCEEDED(hResult)) { ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", d3dIdent.Driver, HIWORD(d3dIdent.DriverVersion.HighPart), LOWORD(d3dIdent.DriverVersion.HighPart), HIWORD(d3dIdent.DriverVersion.LowPart), LOWORD(d3dIdent.DriverVersion.LowPart)); ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); } #endif // Init projection matrix for D3D TnL D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection); lpCtx->matModelView = lpCtx->matProjection; // gld->bUseMesaProjection = TRUE; skip_direct3ddevice_create: // Create buffers to hold primitives lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; // lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); lpCtx->PB2d.dwCreateFlags = D3DVBCAPS_DONOTCLIP | D3DVBCAPS_SYSTEMMEMORY | D3DVBCAPS_WRITEONLY; hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); if (FAILED(hr)) goto return_with_error; lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; // lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); lpCtx->PB3d.dwCreateFlags = D3DVBCAPS_WRITEONLY; hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); if (FAILED(hr)) goto return_with_error; // Zero the pipeline usage counters lpCtx->PipelineUsage.qwMesa.QuadPart = // lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; // Assign drawable to GL private ctx->glPriv = lpCtx; return TRUE; return_with_error: // Clean up and bail _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); SAFE_RELEASE(lpCtx->pDev); SAFE_RELEASE(lpCtx->pD3D); //SAFE_RELEASE(lpCtx->pD3DXContext); lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); return FALSE; }
static BOOL _gldDriverError(void) { ddlogMessage(DDLOG_CRITICAL, szDriverError); return FALSE; }
BOOL gldBuildPixelformatList_DX(void) { D3DX_DEVICEDESC d3dxdd; D3DX_VIDMODEDESC d3ddm; D3DX_SURFACEFORMAT fmt[64]; // 64 should be enough... DWORD dwDeviceIndex; DWORD surfClassFlags; // IDirect3D7 *pD3D = NULL; HRESULT hr; int nSupportedFormats = 0; // Total formats int nDepthOnlyFormats = 0; int nDepthStencilFormats = 0; int i; DGL_pixelFormat *pPF; BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; // char buf[128]; // char cat[8]; // Direct3D (SW or HW) // These are arranged so that 'best' pixelformat // is higher in the list (for ChoosePixelFormat). /* const D3DFORMAT DepthStencil[4] = { D3DX_SF_Z16S0, //D3DX_SF_D16, D3DX_SF_Z15S1, //D3DX_SF_D15S1, D3DX_SF_Z32S0, //D3DX_SF_D32, D3DX_SF_Z24S8, //D3DX_SF_D24S8, //D3DX_SF_D24X8, //D3DX_SF_D24X4S4, };*/ // Dump DX version ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 7.0\n"); // Release any existing pixelformat list if (glb.lpPF) { free(glb.lpPF); } glb.nPixelFormatCount = 0; glb.lpPF = NULL; // // Pixelformats for Direct3D (SW or HW) rendering // dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT; // Dump description D3DXGetDeviceDescription(dwDeviceIndex, &d3dxdd); ddlogPrintf(GLDLOG_SYSTEM, "Device: %s", d3dxdd.driverDesc); // Get display mode D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); #if 0 // Phooey - this don't work... /* // Since D3DXGetMaxSurfaceFormats() can lie to us, we'll need a workaround. // Explicitly test for matching depth/stencil to display bpp. if (d3ddm.bpp <= 16) { if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0)) fmt[nSupportedFormats++] = D3DX_SF_Z16S0; if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z15S1)) fmt[nSupportedFormats++] = D3DX_SF_Z15S1; if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S1Z15)) fmt[nSupportedFormats++] = D3DX_SF_S1Z15; // Didn't find anything? Try default if (nSupportedFormats == 0) { if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0)) fmt[nSupportedFormats++] = D3DX_SF_Z32S0; } } else { if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0)) fmt[nSupportedFormats++] = D3DX_SF_Z32S0; if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z24S8)) fmt[nSupportedFormats++] = D3DX_SF_Z24S8; if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S8Z24)) fmt[nSupportedFormats++] = D3DX_SF_S8Z24; // Didn't find anything? Try default if (nSupportedFormats == 0) { if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0)) fmt[nSupportedFormats++] = D3DX_SF_Z16S0; } } */ // Go the Whole Hog... fmt[nSupportedFormats++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex); #else // // Depth buffer formats WITHOUT stencil // surfClassFlags = D3DX_SC_DEPTHBUFFER; nDepthOnlyFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags); // // Depth buffer formats WITH stencil // surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER; nDepthStencilFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags); // Work out how many formats we have in total if ((nDepthOnlyFormats + nDepthStencilFormats) == 0) return FALSE; // Bail: no compliant pixelformats // Get depth buffer formats WITHOUT stencil surfClassFlags = D3DX_SC_DEPTHBUFFER; for (i=0; i<nDepthOnlyFormats; i++) { D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]); } // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER /* // Get depth buffer formats WITH stencil surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER; for (i=0; i<nDepthStencilFormats; i++) { D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]); } */ #endif // Total count of pixelformats is: // (nSupportedFormats+1)*2 glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat)); glb.nPixelFormatCount = (nSupportedFormats)*2; if (glb.lpPF == NULL) { glb.nPixelFormatCount = 0; return FALSE; } // Get a copy of pointer that we can alter pPF = glb.lpPF; // Cache colour bits from display format // _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); // Get display mode D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); cColorBits = d3ddm.bpp; cAlphaBits = 0; switch (d3ddm.bpp) { case 15: cRedBits = 5; cGreenBits = 5; cBlueBits = 5; break; case 16: cRedBits = 5; cGreenBits = 6; cBlueBits = 5; break; case 24: case 32: cRedBits = 8; cGreenBits = 8; cBlueBits = 8; break; default: cRedBits = 5; cGreenBits = 5; cBlueBits = 5; } // // Add single-buffer formats // /* // Single-buffer, no depth-stencil buffer memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag pPF->pfd.cColorBits = cColorBits; pPF->pfd.cRedBits = cRedBits; pPF->pfd.cGreenBits = cGreenBits; pPF->pfd.cBlueBits = cBlueBits; pPF->pfd.cAlphaBits = cAlphaBits; pPF->pfd.cDepthBits = 0; pPF->pfd.cStencilBits = 0; pPF->dwDriverData = D3DX_SF_UNKNOWN; pPF++;*/ for (i=0; i<nSupportedFormats; i++, pPF++) { memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag pPF->pfd.cColorBits = cColorBits; pPF->pfd.cRedBits = cRedBits; pPF->pfd.cGreenBits = cGreenBits; pPF->pfd.cBlueBits = cBlueBits; pPF->pfd.cAlphaBits = cAlphaBits; _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); pPF->dwDriverData = fmt[i]; } // // Add double-buffer formats // /* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); pPF->pfd.cColorBits = cColorBits; pPF->pfd.cRedBits = cRedBits; pPF->pfd.cGreenBits = cGreenBits; pPF->pfd.cBlueBits = cBlueBits; pPF->pfd.cAlphaBits = cAlphaBits; pPF->pfd.cDepthBits = 0; pPF->pfd.cStencilBits = 0; pPF->dwDriverData = D3DX_SF_UNKNOWN; pPF++;*/ for (i=0; i<nSupportedFormats; i++, pPF++) { memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); pPF->pfd.cColorBits = cColorBits; pPF->pfd.cRedBits = cRedBits; pPF->pfd.cGreenBits = cGreenBits; pPF->pfd.cBlueBits = cBlueBits; pPF->pfd.cAlphaBits = cAlphaBits; _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); pPF->dwDriverData = fmt[i]; } // Popup warning message if non RGB color mode { // This is a hack. KeithH HDC hdcDesktop = GetDC(NULL); DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL); ReleaseDC(0, hdcDesktop); if (dwDisplayBitDepth <= 8) { ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth); MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING); } } // Mark list as 'current' glb.bPixelformatsDirty = FALSE; return TRUE; }
static GLboolean gld_d3d_render_stage_run( GLcontext *ctx, struct tnl_pipeline_stage *stage) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); TNLcontext *tnl; struct vertex_buffer *VB; tnl_render_func *tab; GLint pass; GLD_pb_dx7 *gldPB = &gld->PB3d; DWORD dwFlags; /* static int count = 0; count++; if (count != 2) return GL_FALSE; */ // The "check" function should disable this stage, // but we'll test gld->bUseMesaTnL anyway. if (gld->bUseMesaTnL) { // Do nothing in this stage, but continue pipeline return GL_TRUE; } tnl = TNL_CONTEXT(ctx); VB = &tnl->vb; pass = 0; tnl->Driver.Render.Start( ctx ); #if 0 // For debugging: Useful to see if an app passes colour data in // an unusual format. switch (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->Type) { case GL_FLOAT: ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n"); break; case GL_UNSIGNED_BYTE: ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n"); break; default: ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n"); break; } #endif tnl->Driver.Render.Points = gld_Points3D_DX7; if (ctx->_TriangleCaps & DD_FLATSHADE) { tnl->Driver.Render.Line = gld_Line3DFlat_DX7; tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX7; tnl->Driver.Render.Quad = gld_Quad3DFlat_DX7; } else { tnl->Driver.Render.Line = gld_Line3DSmooth_DX7; tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX7; tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX7; } // _GLD_DX7_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY; _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL)); gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; // Allocate primitive pointers // gldPB->pPoints is always first gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); ASSERT(tnl->Driver.Render.BuildVertices); ASSERT(tnl->Driver.Render.PrimitiveNotify); ASSERT(tnl->Driver.Render.Points); ASSERT(tnl->Driver.Render.Line); ASSERT(tnl->Driver.Render.Triangle); ASSERT(tnl->Driver.Render.Quad); ASSERT(tnl->Driver.Render.ResetLineStipple); ASSERT(tnl->Driver.Render.Interp); ASSERT(tnl->Driver.Render.CopyPV); ASSERT(tnl->Driver.Render.ClippedLine); ASSERT(tnl->Driver.Render.ClippedPolygon); ASSERT(tnl->Driver.Render.Finish); tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts); do { GLuint i, length, flags = 0; for (i = 0 ; !(flags & PRIM_END) ; i += length) { flags = VB->Primitive[i].mode; length= VB->Primitive[i].count; ASSERT(length || (flags & PRIM_END)); ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); if (length) tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); } } while (tnl->Driver.Render.Multipass && tnl->Driver.Render.Multipass( ctx, ++pass )); _GLD_DX7_VB(Unlock(gldPB->pVB)); // _GLD_DX7_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride)); _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_PROJECTION, &gld->matProjection)); _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_WORLD, &gld->matModelView)); if (gldPB->nPoints) { // _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0)); gldPB->nPoints = 0; } if (gldPB->nLines) { // _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines, 0)); gldPB->nLines = 0; } if (gldPB->nTriangles) { // _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles, 0)); gldPB->nTriangles = 0; } return GL_FALSE; /* finished the pipe */ }