static IDirect3DDevice9 *init_d3d9(HMODULE d3d9_handle) { IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0; IDirect3D9 *d3d9_ptr = 0; IDirect3DDevice9 *device_ptr = 0; D3DPRESENT_PARAMETERS present_parameters; HRESULT hr; d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9"); ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n"); if (!d3d9_create) return NULL; d3d9_ptr = d3d9_create(D3D_SDK_VERSION); if (!d3d9_ptr) { skip("could not create D3D9\n"); return NULL; } ZeroMemory(&present_parameters, sizeof(present_parameters)); present_parameters.Windowed = TRUE; present_parameters.hDeviceWindow = create_window(); present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr); if(FAILED(hr)) { skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr); return NULL; } return device_ptr; }
static HRESULT create_device(base *d3dptr, UINT adapter, D3DDEVTYPE devtype, HWND focus, DWORD behavior, present_parameters *params, device **dev) { IDirect3D9 *d3d9 = (IDirect3D9 *)d3dptr->d3dobj; D3DPRESENT_PARAMETERS d3d9params; convert_present_params(params, &d3d9params); return IDirect3D9_CreateDevice(d3d9, adapter, devtype, focus, behavior, &d3d9params, (IDirect3DDevice9 **)dev); }
static int dxva2_device_create9(AVHWDeviceContext *ctx, UINT adapter) { DXVA2DevicePriv *priv = ctx->user_opaque; D3DPRESENT_PARAMETERS d3dpp = dxva2_present_params; D3DDISPLAYMODE d3ddm; HRESULT hr; pDirect3DCreate9 *createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9"); if (!createD3D) { av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n"); return AVERROR_UNKNOWN; } priv->d3d9 = createD3D(D3D_SDK_VERSION); if (!priv->d3d9) { av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n"); return AVERROR_UNKNOWN; } IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm); d3dpp.BackBufferFormat = d3ddm.Format; hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), FF_D3DCREATE_FLAGS, &d3dpp, &priv->d3d9device); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n"); return AVERROR_UNKNOWN; } return 0; }
/** * It creates a Direct3D device usable for DXVA 2 */ static int D3dCreateDevice(vlc_va_t *va) { vlc_va_sys_t *sys = va->sys; /* */ LPDIRECT3D9 (WINAPI *Create9)(UINT SDKVersion); Create9 = (void *)GetProcAddress(sys->hd3d9_dll, "Direct3DCreate9"); if (!Create9) { msg_Err(va, "Cannot locate reference to Direct3DCreate9 ABI in DLL"); return VLC_EGENERIC; } /* */ LPDIRECT3D9 d3dobj; d3dobj = Create9(D3D_SDK_VERSION); if (!d3dobj) { msg_Err(va, "Direct3DCreate9 failed"); return VLC_EGENERIC; } sys->d3dobj = d3dobj; /* */ D3DADAPTER_IDENTIFIER9 *d3dai = &sys->d3dai; if (FAILED(IDirect3D9_GetAdapterIdentifier(sys->d3dobj, D3DADAPTER_DEFAULT, 0, d3dai))) { msg_Warn(va, "IDirect3D9_GetAdapterIdentifier failed"); ZeroMemory(d3dai, sizeof(*d3dai)); } /* */ D3DPRESENT_PARAMETERS *d3dpp = &sys->d3dpp; ZeroMemory(d3dpp, sizeof(*d3dpp)); d3dpp->Flags = D3DPRESENTFLAG_VIDEO; d3dpp->Windowed = TRUE; d3dpp->hDeviceWindow = NULL; d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp->BackBufferCount = 0; /* FIXME what to put here */ d3dpp->BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */ d3dpp->BackBufferWidth = 0; d3dpp->BackBufferHeight = 0; d3dpp->EnableAutoDepthStencil = FALSE; /* Direct3D needs a HWND to create a device, even without using ::Present this HWND is used to alert Direct3D when there's a change of focus window. For now, use GetDesktopWindow, as it looks harmless */ LPDIRECT3DDEVICE9 d3ddev; if (FAILED(IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED, d3dpp, &d3ddev))) { msg_Err(va, "IDirect3D9_CreateDevice failed"); return VLC_EGENERIC; } sys->d3ddev = d3ddev; return VLC_SUCCESS; }
/** * It creates a DirectX video service */ static int hb_d3d_create_device( hb_va_dxva2_t *dxva2 ) { LPDIRECT3D9 (WINAPI *Create9)( UINT SDKVersion ); Create9 = (void*)GetProcAddress( dxva2->hd3d9_dll, TEXT( "Direct3DCreate9" )); if( !Create9 ) { hb_log( "dxva2:Cannot locate reference to Direct3DCreate9 ABI in DLL" ); return HB_WORK_ERROR; } LPDIRECT3D9 d3dobj; d3dobj = Create9( D3D_SDK_VERSION ); if( !d3dobj ) { hb_log( "dxva2:Direct3DCreate9 failed" ); return HB_WORK_ERROR; } dxva2->d3dobj = d3dobj; D3DADAPTER_IDENTIFIER9 *d3dai = &dxva2->d3dai; if( FAILED( IDirect3D9_GetAdapterIdentifier( dxva2->d3dobj, D3DADAPTER_DEFAULT, 0, d3dai ))) { hb_log( "dxva2:IDirect3D9_GetAdapterIdentifier failed" ); memset( d3dai, 0, sizeof(*d3dai)); } PROCGETSHELLWND GetShellWindow; HMODULE hUser32 = GetModuleHandle( "user32" ); GetShellWindow = (PROCGETSHELLWND) GetProcAddress( hUser32, "GetShellWindow" ); D3DPRESENT_PARAMETERS *d3dpp = &dxva2->d3dpp; memset( d3dpp, 0, sizeof(*d3dpp)); d3dpp->Flags = D3DPRESENTFLAG_VIDEO; d3dpp->Windowed = TRUE; d3dpp->hDeviceWindow = NULL; d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp->MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp->BackBufferCount = 0; /* FIXME what to put here */ d3dpp->BackBufferFormat = D3DFMT_X8R8G8B8; /* FIXME what to put here */ d3dpp->BackBufferWidth = 0; d3dpp->BackBufferHeight = 0; d3dpp->EnableAutoDepthStencil = FALSE; LPDIRECT3DDEVICE9 d3ddev; //if (FAILED(IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED, d3dpp, &d3ddev))) if( FAILED( IDirect3D9_CreateDevice( d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED, d3dpp, &d3ddev ))) { hb_log( "dxva2:IDirect3D9_CreateDevice failed" ); return HB_WORK_ERROR; } dxva2->d3ddev = d3ddev; return HB_WORK_OK; }
static int create_device(struct lavc_ctx *s) { DXVA2Context *ctx = s->hwdec_priv; pDirect3DCreate9 *createD3D = NULL; HRESULT hr; D3DPRESENT_PARAMETERS d3dpp = {0}; D3DDISPLAYMODE d3ddm; UINT adapter = D3DADAPTER_DEFAULT; if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) { ctx->d3d9device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device; if (ctx->d3d9device) { IDirect3D9_AddRef(ctx->d3d9device); MP_VERBOSE(ctx, "Using VO-supplied device %p.\n", ctx->d3d9device); return 0; } } ctx->d3dlib = LoadLibrary(L"d3d9.dll"); if (!ctx->d3dlib) { MP_ERR(ctx, "Failed to load D3D9 library\n"); goto fail; } createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9"); if (!createD3D) { MP_ERR(ctx, "Failed to locate Direct3DCreate9\n"); goto fail; } ctx->d3d9 = createD3D(D3D_SDK_VERSION); if (!ctx->d3d9) { MP_ERR(ctx, "Failed to create IDirect3D object\n"); goto fail; } IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm); d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; d3dpp.BackBufferCount = 0; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Flags = D3DPRESENTFLAG_VIDEO; hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &d3dpp, &ctx->d3d9device); if (FAILED(hr)) { MP_ERR(ctx, "Failed to create Direct3D device\n"); goto fail; } return 0; fail: return -1; }
/** * It creates a Direct3D device and the associated resources. */ static int Direct3DOpen(vout_display_t *vd, video_format_t *fmt) { vout_display_sys_t *sys = vd->sys; LPDIRECT3D9 d3dobj = sys->d3dobj; if (Direct3DFillPresentationParameters(vd)) return VLC_EGENERIC; // Create the D3DDevice LPDIRECT3DDEVICE9 d3ddev; UINT AdapterToUse = D3DADAPTER_DEFAULT; D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL; #ifndef NDEBUG // Look for 'NVIDIA PerfHUD' adapter // If it is present, override default settings for (UINT Adapter=0; Adapter< IDirect3D9_GetAdapterCount(d3dobj); ++Adapter) { D3DADAPTER_IDENTIFIER9 Identifier; HRESULT Res; Res = IDirect3D9_GetAdapterIdentifier(d3dobj,Adapter,0,&Identifier); if (strstr(Identifier.Description,"PerfHUD") != 0) { AdapterToUse = Adapter; DeviceType = D3DDEVTYPE_REF; break; } } #endif HRESULT hr = IDirect3D9_CreateDevice(d3dobj, AdapterToUse, DeviceType, sys->hvideownd, D3DCREATE_SOFTWARE_VERTEXPROCESSING| D3DCREATE_MULTITHREADED, &sys->d3dpp, &d3ddev); if (FAILED(hr)) { msg_Err(vd, "Could not create the D3D device! (hr=0x%lX)", hr); return VLC_EGENERIC; } sys->d3ddev = d3ddev; UpdateRects(vd, NULL, NULL, true); if (Direct3DCreateResources(vd, fmt)) { msg_Err(vd, "Failed to allocate resources"); return VLC_EGENERIC; } /* Change the window title bar text */ EventThreadUpdateTitle(sys->event, VOUT_TITLE " (Direct3D output)"); msg_Dbg(vd, "Direct3D device adapter successfully initialized"); return VLC_SUCCESS; }
static void test_qi_base_to_ex(void) { IDirect3D9 *d3d9 = pDirect3DCreate9(D3D_SDK_VERSION); IDirect3D9Ex *d3d9ex = (void *) 0xdeadbeef; IDirect3DDevice9 *device; IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef; HRESULT hr; HWND window = create_window(); D3DPRESENT_PARAMETERS present_parameters; if (!d3d9) { skip("Direct3D9 is not available\n"); return; } hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **) &d3d9ex); ok(hr == E_NOINTERFACE, "IDirect3D9::QueryInterface for IID_IDirect3D9Ex returned %08x, expected E_NOINTERFACE\n", hr); ok(d3d9ex == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9ex); if(d3d9ex) IDirect3D9Ex_Release(d3d9ex); memset(&present_parameters, 0, sizeof(present_parameters)); present_parameters.Windowed = TRUE; present_parameters.hDeviceWindow = window; present_parameters.SwapEffect = D3DSWAPEFFECT_COPY; present_parameters.BackBufferWidth = 640; present_parameters.BackBufferHeight = 480; present_parameters.EnableAutoDepthStencil = FALSE; present_parameters.AutoDepthStencilFormat = D3DFMT_D16; hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); if(FAILED(hr)) { skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n"); goto out; } hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx); ok(hr == E_NOINTERFACE, "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected E_NOINTERFACE\n", hr); ok(deviceEx == NULL, "QueryInterface returned interface %p, expected NULL\n", deviceEx); if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx); IDirect3DDevice9_Release(device); out: IDirect3D9_Release(d3d9); DestroyWindow(window); }
static void test_setting_constants(void) { HWND wnd; IDirect3D9 *d3d; IDirect3DDevice9 *device; D3DPRESENT_PARAMETERS d3dpp; HRESULT hr; ULONG refcnt; /* Create the device to use for our tests */ wnd = CreateWindow("static", "d3dx9_test", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); d3d = Direct3DCreate9(D3D_SDK_VERSION); if (!wnd) { skip("Couldn't create application window\n"); return; } if (!d3d) { skip("Couldn't create IDirect3D9 object\n"); DestroyWindow(wnd); return; } ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device); if (FAILED(hr)) { skip("Failed to create IDirect3DDevice9 object %#x\n", hr); IDirect3D9_Release(d3d); DestroyWindow(wnd); return; } test_setting_basic_table(device); test_setting_arrays_table(device); /* Release resources */ refcnt = IDirect3DDevice9_Release(device); ok(refcnt == 0, "The Direct3D device reference count was %u, should be 0\n", refcnt); refcnt = IDirect3D9_Release(d3d); ok(refcnt == 0, "The Direct3D object referenct count was %u, should be 0\n", refcnt); if (wnd) DestroyWindow(wnd); }
// This must be run before the konvergo main window switches to FS mode. void initD3DDevice(void) { // Boilerplate for creating a "blank" D3D device. // Most of this is copied from FFmpeg (LGPL). pDirect3DCreate9 *createD3D = NULL; HRESULT hr; D3DPRESENT_PARAMETERS d3dpp = {}; D3DDISPLAYMODE d3ddm; UINT adapter = D3DADAPTER_DEFAULT; HMODULE d3dlib = LoadLibraryW(L"d3d9.dll"); if (!d3dlib) { QLOG_ERROR() << "Failed to load D3D9 library"; return; } createD3D = (pDirect3DCreate9 *)GetProcAddress(d3dlib, "Direct3DCreate9"); if (!createD3D) { QLOG_ERROR() << "Failed to locate Direct3DCreate9"; return; } IDirect3D9 *d3d9 = createD3D(D3D_SDK_VERSION); if (!d3d9) { QLOG_ERROR() << "Failed to create IDirect3D object"; return; } IDirect3D9_GetAdapterDisplayMode(d3d9, adapter, &d3ddm); d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; d3dpp.BackBufferCount = 0; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Flags = D3DPRESENTFLAG_VIDEO; hr = IDirect3D9_CreateDevice(d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &d3dpp, &d3ddevice); if (FAILED(hr)) { QLOG_ERROR() << "Failed to create Direct3D device"; return; } QLOG_INFO() << "Successfully created a Direct3D device"; };
/** @brief Create a new backbuffer. Create or Reset the D3D * device. * @return 1 on success, 0 on failure */ static int change_d3d_backbuffer(back_buffer_action_e action) { D3DPRESENT_PARAMETERS present_params; destroy_d3d_surfaces(); /* Grow the backbuffer in the required dimension. */ if (vo_dwidth > priv->cur_backbuf_width) priv->cur_backbuf_width = vo_dwidth; if (vo_dheight > priv->cur_backbuf_height) priv->cur_backbuf_height = vo_dheight; /* The grown backbuffer dimensions are ready and fill_d3d_presentparams * will use them, so we can reset the device. */ fill_d3d_presentparams(&present_params); /* vo_w32_window is w32_common variable. It's a handle to the window. */ if (action == BACKBUFFER_CREATE && FAILED(IDirect3D9_CreateDevice(priv->d3d_handle, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, vo_w32_window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_params, &priv->d3d_device))) { mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Creating Direct3D device failed.\n"); return 0; } if (action == BACKBUFFER_RESET && FAILED(IDirect3DDevice9_Reset(priv->d3d_device, &present_params))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Reseting Direct3D device failed.\n"); return 0; } mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>New backbuffer (%dx%d), VO (%dx%d)\n", present_params.BackBufferWidth, present_params.BackBufferHeight, vo_dwidth, vo_dheight); return 1; }
//=================================================================== // RENDER_API IMPLEMENTATION //=================================================================== JBKRenderResult JBKRender_Create(int64_t hWindow) { // acquire D3D interface gD3D = Direct3DCreate9(D3D_SDK_VERSION); ASSERT(gD3D != NULL, "Failed to load DirectX9!"); memset(&gPresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); gPresentParams.Windowed = TRUE; gPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; gPresentParams.BackBufferFormat = D3DFMT_X8R8G8B8; gPresentParams.BackBufferWidth = 1024; gPresentParams.BackBufferHeight = 768; gPresentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // create D3D device DXCall( IDirect3D9_CreateDevice( gD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)hWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &gPresentParams, &gDevice) ); // set lighting off DXCall( IDirect3DDevice9_SetRenderState(gDevice, D3DRS_LIGHTING, FALSE) ); DXCall( IDirect3DDevice9_SetRenderState(gDevice, D3DRS_ZENABLE, FALSE) ); // create a debug font DXCall( D3DXCreateFont( gDevice, 18, 0, FW_REGULAR, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &gDebugFont) ); return JBK_RENDER_OK; }
static gboolean gst_dx9screencapsrc_start (GstBaseSrc * bsrc) { GstDX9ScreenCapSrc *src = GST_DX9SCREENCAPSRC (bsrc); D3DPRESENT_PARAMETERS d3dpp; HMONITOR monitor; HRESULT res; src->frame_number = -1; ZeroMemory (&d3dpp, sizeof (D3DPRESENT_PARAMETERS)); d3dpp.Windowed = TRUE; d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; d3dpp.BackBufferFormat = src->disp_mode.Format; d3dpp.BackBufferHeight = src->disp_mode.Height; d3dpp.BackBufferWidth = src->disp_mode.Width; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = GetDesktopWindow (); d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; if (src->monitor >= IDirect3D9_GetAdapterCount (g_d3d9)) { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("Specified monitor with index %d not found", src->monitor), (NULL)); return FALSE; } res = IDirect3D9_CreateDevice (g_d3d9, src->monitor, D3DDEVTYPE_HAL, GetDesktopWindow (), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &src->d3d9_device); if (FAILED (res)) return FALSE; monitor = IDirect3D9_GetAdapterMonitor (g_d3d9, src->monitor); GetMonitorInfo (monitor, &src->monitor_info); return SUCCEEDED (IDirect3DDevice9_CreateOffscreenPlainSurface (src->d3d9_device, src->disp_mode.Width, src->disp_mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &src->surface, NULL)); }
static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window) { D3DPRESENT_PARAMETERS present_parameters = {0}; IDirect3DDevice9 *device; DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING; present_parameters.BackBufferWidth = 640; present_parameters.BackBufferHeight = 480; present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8; present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; present_parameters.hDeviceWindow = focus_window; present_parameters.Windowed = TRUE; present_parameters.EnableAutoDepthStencil = FALSE; if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window, behavior_flags, &present_parameters, &device))) return device; return NULL; }
//get the VMT and the hooking functions offsets void GetDevice9Methods() { IDirect3D9 *d3d9_ptr; IDirect3DDevice9* d3dDevice; DWORD* vtablePtr; D3DPRESENT_PARAMETERS d3dpp; static HMODULE d3d9_handle = 0; HWND hWnd = CreateWindowExA(0, "STATIC","dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0); d3d9_handle = LoadLibraryA("d3d9.dll"); d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = 1; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; IDirect3D9_CreateDevice(d3d9_ptr, 0, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dDevice); vtablePtr = (DWORD*)(*((DWORD*)d3dDevice)); present9 = vtablePtr[17] - (DWORD)d3d9_handle; IDirect3DDevice9_Release(d3dDevice); IDirect3D9_Release(d3d9_ptr); FreeLibrary(d3d9_handle); CloseHandle(hWnd); }
static bool d3d9_create_device_internal( void *data, D3DPRESENT_PARAMETERS *d3dpp, void *_d3d, HWND focus_window, unsigned cur_mon_id, DWORD behavior_flags) { LPDIRECT3D9 d3d = (LPDIRECT3D9)_d3d; LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; if (dev && SUCCEEDED(IDirect3D9_CreateDevice(d3d, cur_mon_id, D3DDEVTYPE_HAL, focus_window, behavior_flags, d3dpp, (IDirect3DDevice9**)dev))) return true; return false; }
SDL_Renderer * D3D_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_Renderer *renderer; D3D_RenderData *data; SDL_SysWMinfo windowinfo; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; D3DCAPS9 caps; Uint32 window_flags; int w, h; SDL_DisplayMode fullscreen_mode; D3DMATRIX matrix; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { SDL_free(renderer); SDL_OutOfMemory(); return NULL; } data->d3dDLL = SDL_LoadObject("D3D9.DLL"); if (data->d3dDLL) { IDirect3D9 *(WINAPI * D3DCreate) (UINT SDKVersion); D3DCreate = (IDirect3D9 * (WINAPI *) (UINT)) SDL_LoadFunction(data->d3dDLL, "Direct3DCreate9"); if (D3DCreate) { data->d3d = D3DCreate(D3D_SDK_VERSION); } if (!data->d3d) { SDL_UnloadObject(data->d3dDLL); data->d3dDLL = NULL; } } if (!data->d3d) { SDL_free(renderer); SDL_free(data); SDL_SetError("Unable to create Direct3D interface"); return NULL; } renderer->WindowEvent = D3D_WindowEvent; renderer->CreateTexture = D3D_CreateTexture; renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; renderer->SetRenderTarget = D3D_SetRenderTarget; renderer->UpdateViewport = D3D_UpdateViewport; renderer->RenderClear = D3D_RenderClear; renderer->RenderDrawPoints = D3D_RenderDrawPoints; renderer->RenderDrawLines = D3D_RenderDrawLines; renderer->RenderFillRects = D3D_RenderFillRects; renderer->RenderCopy = D3D_RenderCopy; renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->info = D3D_RenderDriver.info; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; SDL_VERSION(&windowinfo.version); SDL_GetWindowWMInfo(window, &windowinfo); window_flags = SDL_GetWindowFlags(window); SDL_GetWindowSize(window, &w, &h); SDL_GetWindowDisplayMode(window, &fullscreen_mode); SDL_zero(pparams); pparams.hDeviceWindow = windowinfo.info.win.window; pparams.BackBufferWidth = w; pparams.BackBufferHeight = h; if (window_flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = PixelFormatToD3DFMT(fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; if (window_flags & SDL_WINDOW_FULLSCREEN) { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = fullscreen_mode.refresh_rate; } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } if (flags & SDL_RENDERER_PRESENTVSYNC) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } /* FIXME: Which adapter? */ data->adapter = D3DADAPTER_DEFAULT; IDirect3D9_GetDeviceCaps(data->d3d, data->adapter, D3DDEVTYPE_HAL, &caps); result = IDirect3D9_CreateDevice(data->d3d, data->adapter, D3DDEVTYPE_HAL, pparams.hDeviceWindow, D3DCREATE_FPU_PRESERVE | ((caps. DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING), &pparams, &data->device); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("CreateDevice()", result); return NULL; } data->beginScene = SDL_TRUE; data->scaleMode = D3DTEXF_FORCE_DWORD; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("GetSwapChain()", result); return NULL; } result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); if (FAILED(result)) { IDirect3DSwapChain9_Release(chain); D3D_DestroyRenderer(renderer); D3D_SetError("GetPresentParameters()", result); return NULL; } IDirect3DSwapChain9_Release(chain); if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; renderer->info.max_texture_height = caps.MaxTextureHeight; if (caps.NumSimultaneousRTs >= 2) { renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; } /* Set up parameters for rendering */ IDirect3DDevice9_SetVertexShader(data->device, NULL); IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); /* Enable color modulation by diffuse color */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); /* Enable alpha modulation by diffuse alpha */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); /* Disable second texture stage, since we're done */ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); /* Store the default render target */ IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget ); data->currentRenderTarget = NULL; /* Set an identity world and view matrix */ matrix.m[0][0] = 1.0f; matrix.m[0][1] = 0.0f; matrix.m[0][2] = 0.0f; matrix.m[0][3] = 0.0f; matrix.m[1][0] = 0.0f; matrix.m[1][1] = 1.0f; matrix.m[1][2] = 0.0f; matrix.m[1][3] = 0.0f; matrix.m[2][0] = 0.0f; matrix.m[2][1] = 0.0f; matrix.m[2][2] = 1.0f; matrix.m[2][3] = 0.0f; matrix.m[3][0] = 0.0f; matrix.m[3][1] = 0.0f; matrix.m[3][2] = 0.0f; matrix.m[3][3] = 1.0f; IDirect3DDevice9_SetTransform(data->device, D3DTS_WORLD, &matrix); IDirect3DDevice9_SetTransform(data->device, D3DTS_VIEW, &matrix); return renderer; }
HRESULT D3D9_CreateDevice(vlc_object_t *o, d3d9_handle_t *hd3d, HWND hwnd, const video_format_t *source, d3d9_device_t *out) { HRESULT hr; UINT AdapterToUse = D3DADAPTER_DEFAULT; D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL; #ifndef NDEBUG // Look for 'NVIDIA PerfHUD' adapter // If it is present, override default settings for (UINT Adapter=0; Adapter< IDirect3D9_GetAdapterCount(hd3d->obj); ++Adapter) { D3DADAPTER_IDENTIFIER9 Identifier; hr = IDirect3D9_GetAdapterIdentifier(hd3d->obj,Adapter,0,&Identifier); if (SUCCEEDED(hr) && strstr(Identifier.Description,"PerfHUD") != 0) { AdapterToUse = Adapter; DeviceType = D3DDEVTYPE_REF; break; } } #endif /* ** Get device capabilities */ ZeroMemory(&out->caps, sizeof(out->caps)); hr = IDirect3D9_GetDeviceCaps(hd3d->obj, AdapterToUse, DeviceType, &out->caps); if (FAILED(hr)) { msg_Err(o, "Could not read adapter capabilities. (hr=0x%0lx)", hr); return hr; } msg_Dbg(o, "D3D9 device caps 0x%0lX / 0x%0lX", out->caps.DevCaps, out->caps.DevCaps2); /* TODO: need to test device capabilities and select the right render function */ if (!(out->caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) { msg_Err(o, "Device does not support stretching from textures."); return E_INVALIDARG; } if ( source->i_width > out->caps.MaxTextureWidth || source->i_height > out->caps.MaxTextureHeight ) { msg_Err(o, "Textures too large %ux%u max possible: %ux%u", source->i_width, source->i_height, (unsigned) out->caps.MaxTextureWidth, (unsigned) out->caps.MaxTextureHeight); return E_INVALIDARG; } out->adapterId = AdapterToUse; out->hwnd = hwnd; if (D3D9_FillPresentationParameters(hd3d, source, out)) { msg_Err(o, "Could not presentation parameters"); return E_INVALIDARG; } /* */ D3DADAPTER_IDENTIFIER9 d3dai; if (FAILED(IDirect3D9_GetAdapterIdentifier(hd3d->obj, AdapterToUse,0, &d3dai))) { msg_Warn(o, "IDirect3D9_GetAdapterIdentifier failed"); } else { msg_Dbg(o, "Direct3d9 Device: %s %lx %lx %lx", d3dai.Description, d3dai.VendorId, d3dai.DeviceId, d3dai.Revision ); } DWORD thread_modes[] = { D3DCREATE_MULTITHREADED, 0 }; DWORD vertex_modes[] = { D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DCREATE_MIXED_VERTEXPROCESSING, D3DCREATE_SOFTWARE_VERTEXPROCESSING }; for (size_t t = 0; t < ARRAY_SIZE(thread_modes); t++) { for (size_t v = 0; v < ARRAY_SIZE(vertex_modes); v++) { DWORD creationFlags = thread_modes[t] | vertex_modes[v]; if (hd3d->use_ex) hr = IDirect3D9Ex_CreateDeviceEx(hd3d->objex, AdapterToUse, DeviceType, hwnd, creationFlags, &out->pp, NULL, &out->devex); else hr = IDirect3D9_CreateDevice(hd3d->obj, AdapterToUse, DeviceType, hwnd, creationFlags, &out->pp, &out->dev); if (SUCCEEDED(hr)) { out->owner = true; return hr; } } } msg_Err(o, "failed to create the D3D9%s device %d/%d. (hr=0x%lX)", hd3d->use_ex?"Ex":"", AdapterToUse, DeviceType, hr); return hr; }
SDL_Renderer * D3D_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata; SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_Renderer *renderer; D3D_RenderData *data; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; D3DCAPS9 caps; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { D3D_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } data->d3d = videodata->d3d; renderer->DisplayModeChanged = D3D_DisplayModeChanged; renderer->CreateTexture = D3D_CreateTexture; renderer->QueryTexturePixels = D3D_QueryTexturePixels; renderer->SetTexturePalette = D3D_SetTexturePalette; renderer->GetTexturePalette = D3D_GetTexturePalette; renderer->SetTextureColorMod = D3D_SetTextureColorMod; renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod; renderer->SetTextureBlendMode = D3D_SetTextureBlendMode; renderer->SetTextureScaleMode = D3D_SetTextureScaleMode; renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; renderer->DirtyTexture = D3D_DirtyTexture; renderer->RenderPoint = D3D_RenderPoint; renderer->RenderLine = D3D_RenderLine; renderer->RenderFill = D3D_RenderFill; renderer->RenderCopy = D3D_RenderCopy; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->info = D3D_RenderDriver.info; renderer->window = window->id; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; SDL_zero(pparams); pparams.BackBufferWidth = window->w; pparams.BackBufferHeight = window->h; if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = PixelFormatToD3DFMT(display->fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } if (flags & SDL_RENDERER_PRESENTFLIP2) { pparams.BackBufferCount = 2; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTFLIP3) { pparams.BackBufferCount = 3; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTCOPY) { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_COPY; } else { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; } if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = display->fullscreen_mode.refresh_rate; } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } if (flags & SDL_RENDERER_PRESENTVSYNC) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } IDirect3D9_GetDeviceCaps(videodata->d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); result = IDirect3D9_CreateDevice(videodata->d3d, D3DADAPTER_DEFAULT, /* FIXME */ D3DDEVTYPE_HAL, windowdata->hwnd, (caps. DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pparams, &data->device); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("CreateDevice()", result); return NULL; } data->beginScene = SDL_TRUE; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("GetSwapChain()", result); return NULL; } result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); if (FAILED(result)) { IDirect3DSwapChain9_Release(chain); D3D_DestroyRenderer(renderer); D3D_SetError("GetPresentParameters()", result); return NULL; } IDirect3DSwapChain9_Release(chain); switch (pparams.SwapEffect) { case D3DSWAPEFFECT_COPY: renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; break; case D3DSWAPEFFECT_FLIP: switch (pparams.BackBufferCount) { case 2: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; break; case 3: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; break; } break; case D3DSWAPEFFECT_DISCARD: renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD; break; } if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; renderer->info.max_texture_height = caps.MaxTextureHeight; /* Set up parameters for rendering */ IDirect3DDevice9_SetVertexShader(data->device, NULL); IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); /* Enable color modulation by diffuse color */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); /* Enable alpha modulation by diffuse alpha */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); /* Disable second texture stage, since we're done */ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); return renderer; }
SDL_Renderer * D3D_CreateRenderer(SDL_Window * window, Uint32 flags) { SDL_VideoDisplay *display = window->display; SDL_VideoData *videodata = (SDL_VideoData *) display->device->driverdata; SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata; SDL_Renderer *renderer; D3D_RenderData *data; HRESULT result; D3DPRESENT_PARAMETERS pparams; IDirect3DSwapChain9 *chain; D3DCAPS9 caps; renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); if (!renderer) { SDL_OutOfMemory(); return NULL; } data = (D3D_RenderData *) SDL_calloc(1, sizeof(*data)); if (!data) { D3D_DestroyRenderer(renderer); SDL_OutOfMemory(); return NULL; } data->d3d = videodata->d3d; videodata->render = RENDER_D3D; renderer->DisplayModeChanged = D3D_DisplayModeChanged; renderer->CreateTexture = D3D_CreateTexture; renderer->QueryTexturePixels = D3D_QueryTexturePixels; renderer->SetTexturePalette = D3D_SetTexturePalette; renderer->GetTexturePalette = D3D_GetTexturePalette; renderer->SetTextureColorMod = D3D_SetTextureColorMod; renderer->SetTextureAlphaMod = D3D_SetTextureAlphaMod; renderer->SetTextureBlendMode = D3D_SetTextureBlendMode; renderer->SetTextureScaleMode = D3D_SetTextureScaleMode; renderer->UpdateTexture = D3D_UpdateTexture; renderer->LockTexture = D3D_LockTexture; renderer->UnlockTexture = D3D_UnlockTexture; renderer->DirtyTexture = D3D_DirtyTexture; renderer->RenderDrawPoints = D3D_RenderDrawPoints; renderer->RenderDrawLines = D3D_RenderDrawLines; renderer->RenderDrawRects = D3D_RenderDrawRects; renderer->RenderFillRects = D3D_RenderFillRects; renderer->RenderCopy = D3D_RenderCopy; renderer->RenderReadPixels = D3D_RenderReadPixels; renderer->RenderWritePixels = D3D_RenderWritePixels; renderer->RenderPresent = D3D_RenderPresent; renderer->DestroyTexture = D3D_DestroyTexture; renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->info = D3D_RenderDriver.info; renderer->window = window; renderer->driverdata = data; renderer->info.flags = SDL_RENDERER_ACCELERATED; SDL_zero(pparams); pparams.BackBufferWidth = window->w; pparams.BackBufferHeight = window->h; if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.BackBufferFormat = PixelFormatToD3DFMT(window->fullscreen_mode.format); } else { pparams.BackBufferFormat = D3DFMT_UNKNOWN; } if (flags & SDL_RENDERER_PRESENTFLIP2) { pparams.BackBufferCount = 2; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTFLIP3) { pparams.BackBufferCount = 3; pparams.SwapEffect = D3DSWAPEFFECT_FLIP; } else if (flags & SDL_RENDERER_PRESENTCOPY) { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_COPY; } else { pparams.BackBufferCount = 1; pparams.SwapEffect = D3DSWAPEFFECT_DISCARD; } if (window->flags & SDL_WINDOW_FULLSCREEN) { pparams.Windowed = FALSE; pparams.FullScreen_RefreshRateInHz = window->fullscreen_mode.refresh_rate; } else { pparams.Windowed = TRUE; pparams.FullScreen_RefreshRateInHz = 0; } if (flags & SDL_RENDERER_PRESENTVSYNC) { pparams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; } else { pparams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } data->adapter = D3D_FindAdapter(videodata->d3d, display); IDirect3D9_GetDeviceCaps(videodata->d3d, data->adapter, D3DDEVTYPE_HAL, &caps); result = IDirect3D9_CreateDevice(videodata->d3d, data->adapter, D3DDEVTYPE_HAL, windowdata->hwnd, (caps. DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pparams, &data->device); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("CreateDevice()", result); return NULL; } data->beginScene = SDL_TRUE; /* Get presentation parameters to fill info */ result = IDirect3DDevice9_GetSwapChain(data->device, 0, &chain); if (FAILED(result)) { D3D_DestroyRenderer(renderer); D3D_SetError("GetSwapChain()", result); return NULL; } result = IDirect3DSwapChain9_GetPresentParameters(chain, &pparams); if (FAILED(result)) { IDirect3DSwapChain9_Release(chain); D3D_DestroyRenderer(renderer); D3D_SetError("GetPresentParameters()", result); return NULL; } IDirect3DSwapChain9_Release(chain); switch (pparams.SwapEffect) { case D3DSWAPEFFECT_COPY: renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; break; case D3DSWAPEFFECT_FLIP: switch (pparams.BackBufferCount) { case 2: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; break; case 3: renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; break; } break; case D3DSWAPEFFECT_DISCARD: renderer->info.flags |= SDL_RENDERER_PRESENTDISCARD; break; } if (pparams.PresentationInterval == D3DPRESENT_INTERVAL_ONE) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } data->pparams = pparams; IDirect3DDevice9_GetDeviceCaps(data->device, &caps); renderer->info.max_texture_width = caps.MaxTextureWidth; renderer->info.max_texture_height = caps.MaxTextureHeight; /* Set up parameters for rendering */ IDirect3DDevice9_SetVertexShader(data->device, NULL); IDirect3DDevice9_SetFVF(data->device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); IDirect3DDevice9_SetRenderState(data->device, D3DRS_ZENABLE, D3DZB_FALSE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(data->device, D3DRS_LIGHTING, FALSE); /* Enable color modulation by diffuse color */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); /* Enable alpha modulation by diffuse alpha */ IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(data->device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); /* Disable second texture stage, since we're done */ IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(data->device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); { #ifdef ASSEMBLE_SHADER const char *shader_text = "ps_1_1\n" "def c0, 0, 0, 0, 0.496\n" "def c1, 0, 0, 0, 1\n" "def c2, 0, 0, 0, -1\n" "tex t0\n" "mul r1, t0, v0\n" "add r0, r1, c0\n" "cnd r0, r0.a, c1, c2\n" "add r0, r0, r1\n"; LPD3DXBUFFER pCode; // buffer with the assembled shader code LPD3DXBUFFER pErrorMsgs; // buffer with error messages LPDWORD shader_data; DWORD shader_size; result = D3DXAssembleShader( shader_text, SDL_strlen(shader_text), NULL, NULL, 0, &pCode, &pErrorMsgs ); if (FAILED(result)) { D3D_SetError("D3DXAssembleShader()", result); } shader_data = (DWORD*)pCode->lpVtbl->GetBufferPointer(pCode); shader_size = pCode->lpVtbl->GetBufferSize(pCode); #else const DWORD shader_data[] = { 0xffff0101,0x00000051,0xa00f0000,0x00000000,0x00000000,0x00000000, 0x3efdf3b6,0x00000051,0xa00f0001,0x00000000,0x00000000,0x00000000, 0x3f800000,0x00000051,0xa00f0002,0x00000000,0x00000000,0x00000000, 0xbf800000,0x00000042,0xb00f0000,0x00000005,0x800f0001,0xb0e40000, 0x90e40000,0x00000002,0x800f0000,0x80e40001,0xa0e40000,0x00000050, 0x800f0000,0x80ff0000,0xa0e40001,0xa0e40002,0x00000002,0x800f0000, 0x80e40000,0x80e40001,0x0000ffff }; #endif result = IDirect3DDevice9_CreatePixelShader(data->device, shader_data, &data->ps_mask); if (FAILED(result)) { D3D_SetError("CreatePixelShader()", result); } } return renderer; }
void initD3D9() { #ifdef __WIN32__ static HMODULE d3d9_handle = 0; IDirect3D9 *(__stdcall * d3d9_create)(UINT SDKVersion) = NULL; D3DPRESENT_PARAMETERS present_parameters; D3DADAPTER_IDENTIFIER9 identifier; HRESULT hr; HWND hwnd; d3d9_handle = LoadLibraryA("d3d9.dll"); if (!d3d9_handle) { fprintf(stderr, "Could not load d3d9.dll\n"); return; } d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9"); if (!d3d9_create) { fprintf(stderr, "Could not get address of Direct3DCreate9\n"); return; } gD3D9Ptr = d3d9_create(D3D_SDK_VERSION); if (!gD3D9Ptr) { fprintf(stderr, "could not create D3D9\n"); return; } hwnd = createWindowWin32(); ZeroMemory(&present_parameters, sizeof(present_parameters)); present_parameters.Windowed = FALSE; present_parameters.hDeviceWindow = hwnd; present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; present_parameters.BackBufferWidth = DEFAULT_WINDOW_WIDTH;; present_parameters.BackBufferHeight = DEFAULT_WINDOW_HEIGHT; present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8; present_parameters.EnableAutoDepthStencil = TRUE; present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; present_parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; memset(&identifier, 0, sizeof(identifier)); IDirect3D9_GetAdapterIdentifier(gD3D9Ptr, 0, 0, &identifier); printf("Driver string: \"%s\"\n", identifier.Driver); printf("Description string: \"%s\"\n", identifier.Description); printf("Device name string: \"%s\"\n", identifier.DeviceName); printf("Driver version %d.%d.%d.%d\n", HIWORD(identifier.DriverVersion.HighPart), LOWORD(identifier.DriverVersion.HighPart), HIWORD(identifier.DriverVersion.LowPart), LOWORD(identifier.DriverVersion.LowPart)); hr = IDirect3D9_CreateDevice(gD3D9Ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &gDevicePtr); if(FAILED(hr)) { present_parameters.AutoDepthStencilFormat = D3DFMT_D16; hr = IDirect3D9_CreateDevice(gD3D9Ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &gDevicePtr); if(FAILED(hr)) { hr = IDirect3D9_CreateDevice(gD3D9Ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &gDevicePtr); } } if (FAILED(hr) || !gDevicePtr) { fprintf(stderr, "Creating the device failed\n"); return; } /* Not yet being used */ if (0) createDummyTexD3D9(); createShadersD3D9(); createVertexBuffersD3D9(); IDirect3DDevice9_GetBackBuffer(gDevicePtr, 0, 0, D3DBACKBUFFER_TYPE_MONO, &gDeviceBackBufferPtr); ShowWindow(hwnd, TRUE); UpdateWindow(hwnd); while (!gIsQuitting) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } displayD3D9(); } #else fprintf(stderr, "ERROR: D3D9 not supported on this platform\n"); #endif }
static int dxva2_alloc(AVCodecContext *s) { HwAccelContext *hac = s->opaque; DXVA2Context *ctx; pDirect3DCreate9 *createD3D = NULL; pCreateDeviceManager9 *createDeviceManager = NULL; HRESULT hr; D3DPRESENT_PARAMETERS d3dpp = {0}; D3DDISPLAYMODE d3ddm; unsigned resetToken = 0; UINT adapter = D3DADAPTER_DEFAULT; ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM); ctx->deviceHandle = INVALID_HANDLE_VALUE; hac->hwaccel_ctx = ctx; hac->hwaccel_uninit = dxva2_uninit; hac->hwaccel_get_buffer = dxva2_get_buffer; hac->hwaccel_retrieve_data = dxva2_retrieve_data; ctx->d3dlib = LoadLibrary("d3d9.dll"); if (!ctx->d3dlib) { av_log(NULL, loglevel, "Failed to load D3D9 library\n"); goto fail; } ctx->dxva2lib = LoadLibrary("dxva2.dll"); if (!ctx->dxva2lib) { av_log(NULL, loglevel, "Failed to load DXVA2 library\n"); goto fail; } createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9"); if (!createD3D) { av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n"); goto fail; } createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); if (!createDeviceManager) { av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); goto fail; } ctx->d3d9 = createD3D(D3D_SDK_VERSION); if (!ctx->d3d9) { av_log(NULL, loglevel, "Failed to create IDirect3D object\n"); goto fail; } if (hac->hwaccel_device) { adapter = atoi(hac->hwaccel_device); av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter); } IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm); d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; d3dpp.BackBufferCount = 0; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Flags = D3DPRESENTFLAG_VIDEO; hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &d3dpp, &ctx->d3d9device); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create Direct3D device\n"); goto fail; } hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create Direct3D device manager\n"); goto fail; } hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n"); goto fail; } hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to open device handle\n"); goto fail; } hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); if (FAILED(hr)) { av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); goto fail; } ctx->tmp_frame = av_frame_alloc(); if (!ctx->tmp_frame) goto fail; s->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); if (!s->hwaccel_context) goto fail; return 0; fail: dxva2_uninit(s); return AVERROR(EINVAL); }
HRESULT video_canvas_reset_dx9(video_canvas_t *canvas) { LPDIRECT3DSWAPCHAIN9 d3dsc; HRESULT ddresult; if ((canvas->d3dsurface != NULL) && (S_OK != IDirect3DSurface9_Release(canvas->d3dsurface)) || (canvas->d3ddev != NULL && ((S_OK != IDirect3DDevice9_GetSwapChain(canvas->d3ddev, 0, &d3dsc)) || (S_OK != IDirect3DSwapChain9_Release(d3dsc))) )) { log_debug("video_dx9: Failed to release the DirectX9 device resources!"); } canvas->d3dsurface = NULL; //if (canvas->d3dpp.Windowed == 0) { // int device, width, height, bitdepth, refreshrate; // GetCurrentModeParameters(&device, &width, &height, &bitdepth, &refreshrate); // canvas->d3dpp.BackBufferWidth = width; // canvas->d3dpp.BackBufferHeight = height; //} else { RECT wrect; GetClientRect(canvas->render_hwnd, &wrect); canvas->d3dpp.BackBufferWidth = wrect.right - wrect.left; canvas->d3dpp.BackBufferHeight = wrect.bottom - wrect.top; //} if (dx_primary_surface_rendering) { canvas->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; } else { canvas->d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } if (canvas->d3ddev == NULL) { if (S_OK != IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, canvas->render_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &canvas->d3dpp, &canvas->d3ddev)) { log_debug("video_dx9: Failed to create the DirectX9 device!"); return -1; } } else { if (S_OK != (ddresult = IDirect3DDevice9_Reset( canvas->d3ddev, &canvas->d3dpp))) { log_debug("video_dx9: Failed to reset the DirectX9 device!"); } } if (S_OK != (ddresult = IDirect3DDevice9_CreateOffscreenPlainSurface( canvas->d3ddev, canvas->draw_buffer->canvas_physical_width, canvas->draw_buffer->canvas_physical_height, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &canvas->d3dsurface, NULL))) { log_debug("video_dx9: Failed to create new offscreen surface!"); return ddresult; } return IDirect3DDevice9_TestCooperativeLevel(canvas->d3ddev); }
static int dxva2_init_decoder(struct lavc_ctx *s, int w, int h) { HRESULT hr; int ret = -1; struct priv *p = s->hwdec_priv; TA_FREEP(&p->decoder_pool); int n_surfaces = hwdec_get_max_refs(s) + ADDITIONAL_SURFACES; IDirect3DSurface9 **surfaces = NULL; IDirectXVideoDecoder *decoder = NULL; void *tmp = talloc_new(NULL); UINT n_guids; GUID *device_guids; hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids( p->decoder_service, &n_guids, &device_guids); if (FAILED(hr)) { MP_ERR(p, "Failed to retrieve decoder device GUIDs: %s\n", mp_HRESULT_to_str(hr)); goto done; } dump_decoder_info(s, device_guids, n_guids); struct d3d_decoder_fmt fmt = d3d_select_decoder_mode(s, device_guids, n_guids, get_dxfmt_cb); CoTaskMemFree(device_guids); if (fmt.mpfmt_decoded == IMGFMT_NONE) { MP_ERR(p, "Failed to find a suitable decoder\n"); goto done; } p->mpfmt_decoded = fmt.mpfmt_decoded; struct mp_image_pool *decoder_pool = talloc_steal(tmp, mp_image_pool_new(n_surfaces)); DXVA2_ConfigPictureDecode *decoder_config = talloc_zero(decoder_pool, DXVA2_ConfigPictureDecode); int w_align = w, h_align = h; d3d_surface_align(s, &w_align, &h_align); DXVA2_VideoDesc video_desc ={ .SampleWidth = w, .SampleHeight = h, .Format = fmt.dxfmt_decoded, }; UINT n_configs = 0; DXVA2_ConfigPictureDecode *configs = NULL; hr = IDirectXVideoDecoderService_GetDecoderConfigurations( p->decoder_service, fmt.guid, &video_desc, NULL, &n_configs, &configs); if (FAILED(hr)) { MP_ERR(p, "Unable to retrieve decoder configurations: %s\n", mp_HRESULT_to_str(hr)); goto done; } unsigned max_score = 0; for (UINT i = 0; i < n_configs; i++) { unsigned score = d3d_decoder_config_score( s, &configs[i].guidConfigBitstreamEncryption, configs[i].ConfigBitstreamRaw); if (score > max_score) { max_score = score; *decoder_config = configs[i]; } } CoTaskMemFree(configs); if (!max_score) { MP_ERR(p, "Failed to find a suitable decoder configuration\n"); goto done; } surfaces = talloc_zero_array(decoder_pool, IDirect3DSurface9*, n_surfaces); hr = IDirectXVideoDecoderService_CreateSurface( p->decoder_service, w_align, h_align, n_surfaces - 1, fmt.dxfmt_decoded, D3DPOOL_DEFAULT, 0, DXVA2_VideoDecoderRenderTarget, surfaces, NULL); if (FAILED(hr)) { MP_ERR(p, "Failed to create %d video surfaces: %s\n", n_surfaces, mp_HRESULT_to_str(hr)); goto done; } hr = IDirectXVideoDecoderService_CreateVideoDecoder( p->decoder_service, fmt.guid, &video_desc, decoder_config, surfaces, n_surfaces, &decoder); if (FAILED(hr)) { MP_ERR(p, "Failed to create DXVA2 video decoder: %s\n", mp_HRESULT_to_str(hr)); goto done; } for (int i = 0; i < n_surfaces; i++) { struct mp_image *img = dxva2_new_ref(decoder, surfaces[i], w, h); if (!img) { MP_ERR(p, "Failed to create DXVA2 image\n"); goto done; } mp_image_pool_add(decoder_pool, img); // transferred to pool } // Pass required information on to ffmpeg. struct dxva_context *dxva_ctx = s->avctx->hwaccel_context; dxva_ctx->cfg = decoder_config; dxva_ctx->decoder = decoder; dxva_ctx->surface_count = n_surfaces; dxva_ctx->surface = surfaces; dxva_ctx->workaround = is_clearvideo(fmt.guid) ? FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO : 0; p->decoder_pool = talloc_steal(NULL, decoder_pool); ret = 0; done: // On success, `p->decoder_pool` mp_images still hold refs to `surfaces` and // `decoder`, so the pointers in the ffmpeg `dxva_context` strcture remain // valid for the lifetime of the pool. if (surfaces) { for (int i = 0; i < n_surfaces; i++) IDirect3DSurface9_Release(surfaces[i]); } if (decoder) IDirectXVideoDecoder_Release(decoder); talloc_free(tmp); return ret; } static void destroy_device(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (p->device) IDirect3DDevice9_Release(p->device); if (p->d3d9) IDirect3D9_Release(p->d3d9); if (p->d3d9_dll) FreeLibrary(p->d3d9_dll); if (p->dxva2_dll) FreeLibrary(p->dxva2_dll); } static bool create_device(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; p->d3d9_dll = LoadLibrary(L"d3d9.dll"); if (!p->d3d9_dll) { MP_ERR(p, "Failed to load D3D9 library\n"); return false; } IDirect3D9* (WINAPI *Direct3DCreate9)(UINT) = (void *)GetProcAddress(p->d3d9_dll, "Direct3DCreate9"); if (!Direct3DCreate9) { MP_ERR(p, "Failed to locate Direct3DCreate9\n"); return false; } p->d3d9 = Direct3DCreate9(D3D_SDK_VERSION); if (!p->d3d9) { MP_ERR(p, "Failed to create IDirect3D object\n"); return false; } UINT adapter = D3DADAPTER_DEFAULT; D3DDISPLAYMODE display_mode; IDirect3D9_GetAdapterDisplayMode(p->d3d9, adapter, &display_mode); D3DPRESENT_PARAMETERS present_params = { .Windowed = TRUE, .BackBufferWidth = 640, .BackBufferHeight = 480, .BackBufferCount = 0, .BackBufferFormat = display_mode.Format, .SwapEffect = D3DSWAPEFFECT_DISCARD, .Flags = D3DPRESENTFLAG_VIDEO, }; HRESULT hr = IDirect3D9_CreateDevice(p->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &present_params, &p->device); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D device: %s\n", mp_HRESULT_to_str(hr)); return false; } return true; } static void dxva2_uninit(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (!p) return; av_freep(&s->avctx->hwaccel_context); talloc_free(p->decoder_pool); if (p->decoder_service) IDirectXVideoDecoderService_Release(p->decoder_service); if (p->device_manager && p->device_handle != INVALID_HANDLE_VALUE) IDirect3DDeviceManager9_CloseDeviceHandle(p->device_manager, p->device_handle); if (p->device_manager) IDirect3DDeviceManager9_Release(p->device_manager); destroy_device(s); TA_FREEP(&s->hwdec_priv); } static int dxva2_init(struct lavc_ctx *s) { HRESULT hr; struct priv *p = talloc_zero(NULL, struct priv); if (!p) return -1; s->hwdec_priv = p; p->device_handle = INVALID_HANDLE_VALUE; p->log = mp_log_new(s, s->log, "dxva2"); if (s->hwdec->type == HWDEC_DXVA2_COPY) { mp_check_gpu_memcpy(p->log, NULL); p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) p->device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device; if (p->device) { IDirect3D9_AddRef(p->device); MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device); } else if (s->hwdec->type == HWDEC_DXVA2) { MP_ERR(p, "No Direct3D device provided for native dxva2 decoding\n"); goto fail; } else { if (!create_device(s)) goto fail; } p->dxva2_dll = LoadLibrary(L"dxva2.dll"); if (!p->dxva2_dll) { MP_ERR(p, "Failed to load DXVA2 library\n"); goto fail; } HRESULT (WINAPI *CreateDeviceManager9)(UINT *, IDirect3DDeviceManager9 **) = (void *)GetProcAddress(p->dxva2_dll, "DXVA2CreateDirect3DDeviceManager9"); if (!CreateDeviceManager9) { MP_ERR(p, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); goto fail; } unsigned reset_token = 0; hr = CreateDeviceManager9(&reset_token, &p->device_manager); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D device manager: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_ResetDevice(p->device_manager, p->device, reset_token); if (FAILED(hr)) { MP_ERR(p, "Failed to bind Direct3D device to device manager: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_OpenDeviceHandle(p->device_manager, &p->device_handle); if (FAILED(hr)) { MP_ERR(p, "Failed to open device handle: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = IDirect3DDeviceManager9_GetVideoService( p->device_manager, p->device_handle, &IID_IDirectXVideoDecoderService, (void **)&p->decoder_service); if (FAILED(hr)) { MP_ERR(p, "Failed to create IDirectXVideoDecoderService: %s\n", mp_HRESULT_to_str(hr)); goto fail; } s->avctx->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); if (!s->avctx->hwaccel_context) goto fail; return 0; fail: dxva2_uninit(s); return -1; } static int dxva2_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, const char *codec) { hwdec_request_api(info, "dxva2"); // dxva2-copy can do without external context; dxva2 requires it. if (hwdec->type != HWDEC_DXVA2_COPY) { if (!info || !info->hwctx || !info->hwctx->d3d_ctx || info->hwctx->type == HWDEC_DXVA2_COPY || !info->hwctx->d3d_ctx->d3d9_device) return HWDEC_ERR_NO_CTX; } return d3d_probe_codec(codec); }
/** \fn setup \brief Allocate stuff for a given display with/height. It is called again each time the zoom is changed */ bool dxvaRender::setup() { D3DVIEWPORT9 viewPort = {0, 0, displayWidth, displayHeight, 0, 1}; ADM_info("D3D (re)Setting up \n"); D3DPRESENT_PARAMETERS presentationParameters; memset(&presentationParameters, 0, sizeof(presentationParameters)); presentationParameters.Windowed = TRUE; presentationParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; // We could use copy, but discard seems faster according to ms presentationParameters.Flags = D3DPRESENTFLAG_VIDEO; presentationParameters.hDeviceWindow = windowId; presentationParameters.BackBufferWidth = displayWidth; presentationParameters.BackBufferHeight = displayHeight; presentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE; presentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE; presentationParameters.BackBufferFormat = displayMode.Format; presentationParameters.BackBufferCount = 1; presentationParameters.EnableAutoDepthStencil = FALSE; #ifndef REUSE_DEVICE if(ADM_FAILED(IDirect3D9_CreateDevice( d3dHandle, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, presentationParameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentationParameters, &d3dDevice))) { ADM_warning("Failed to create D3D device\n"); return false; } #else d3dDevice=admD3D::getDevice(); #endif // D3DFORMAT yv12=(D3DFORMAT)MAKEFOURCC('Y','V','1','2'); // if( ADM_FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface( d3dDevice, displayWidth,displayHeight, displayMode.Format, D3DPOOL_DEFAULT, &mySurface, NULL))) { ADM_warning("D3D Cannot create surface\n"); return false; } if( ADM_FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface( d3dDevice, imageWidth,imageHeight, yv12, D3DPOOL_DEFAULT, &myYV12Surface, NULL))) { ADM_warning("D3D Cannot create surface\n"); return false; } // put some defaults IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_SRCBLEND, D3DBLEND_ONE); IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ALPHAFUNC, D3DCMP_GREATER); IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ALPHAREF, (DWORD)0x0); IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_LIGHTING, FALSE); IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // if(ADM_FAILED(IDirect3DDevice9_SetViewport(d3dDevice, &viewPort))) { ADM_warning("D3D Cannot set D3D viewport\n"); return false; } scaler=new ADMColorScalerFull(ADM_CS_BICUBIC,imageWidth,imageHeight,displayWidth,displayHeight, ADM_COLOR_YV12, ADM_COLOR_RGB32A ); videoBuffer=new uint8_t[displayWidth*displayHeight*4]; panScan.left =0; panScan.right =imageWidth-1; panScan.top =0; panScan.bottom=imageHeight-1; targetRect.left =0; targetRect.right =displayWidth-1; targetRect.top =0; targetRect.bottom=displayHeight-1; ADM_info("Setup done\n"); return true; }
static void test_qi_ex_to_base(void) { IDirect3D9 *d3d9 = (void *) 0xdeadbeef; IDirect3D9Ex *d3d9ex; IDirect3DDevice9 *device; IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef; HRESULT hr; HWND window = create_window(); D3DPRESENT_PARAMETERS present_parameters; ULONG ref; hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex); ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Direct3DCreate9Ex returned %08x\n", hr); if(FAILED(hr)) { skip("Direct3D9Ex is not available\n"); goto out; } hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9); ok(hr == D3D_OK, "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n", hr); ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef, "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9); ref = getref((IUnknown *) d3d9ex); ok(ref == 2, "IDirect3D9Ex refcount is %d, expected 2\n", ref); ref = getref((IUnknown *) d3d9); ok(ref == 2, "IDirect3D9 refcount is %d, expected 2\n", ref); memset(&present_parameters, 0, sizeof(present_parameters)); present_parameters.Windowed = TRUE; present_parameters.hDeviceWindow = window; present_parameters.SwapEffect = D3DSWAPEFFECT_COPY; present_parameters.BackBufferWidth = 640; present_parameters.BackBufferHeight = 480; present_parameters.EnableAutoDepthStencil = FALSE; present_parameters.AutoDepthStencilFormat = D3DFMT_D16; /* First, try to create a normal device with IDirect3D9Ex::CreateDevice and QI it for IDirect3DDevice9Ex */ hr = IDirect3D9Ex_CreateDevice(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); if(FAILED(hr)) { skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n"); goto out; } hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx); ok(hr == D3D_OK, "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n", hr); ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef, "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx); ref = getref((IUnknown *) device); ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref); ref = getref((IUnknown *) deviceEx); ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref); if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx); IDirect3DDevice9_Release(device); /* Next, try to create a normal device with IDirect3D9::CreateDevice(non-ex) and QI it */ hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); if(FAILED(hr)) { skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n"); goto out; } hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx); ok(hr == D3D_OK, "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n", hr); ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef, "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx); ref = getref((IUnknown *) device); ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref); ref = getref((IUnknown *) deviceEx); ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref); if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx); IDirect3DDevice9_Release(device); IDirect3D9_Release(d3d9); IDirect3D9Ex_Release(d3d9ex); out: DestroyWindow(window); }
static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { AVDXVA2DeviceContext *hwctx = ctx->hwctx; DXVA2DevicePriv *priv; pDirect3DCreate9 *createD3D = NULL; pCreateDeviceManager9 *createDeviceManager = NULL; D3DPRESENT_PARAMETERS d3dpp = {0}; D3DDISPLAYMODE d3ddm; unsigned resetToken = 0; UINT adapter = D3DADAPTER_DEFAULT; HRESULT hr; if (device) adapter = atoi(device); priv = av_mallocz(sizeof(*priv)); if (!priv) return AVERROR(ENOMEM); ctx->user_opaque = priv; ctx->free = dxva2_device_free; priv->device_handle = INVALID_HANDLE_VALUE; priv->d3dlib = LoadLibrary("d3d9.dll"); if (!priv->d3dlib) { av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n"); return AVERROR_UNKNOWN; } priv->dxva2lib = LoadLibrary("dxva2.dll"); if (!priv->dxva2lib) { av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n"); return AVERROR_UNKNOWN; } createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9"); if (!createD3D) { av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n"); return AVERROR_UNKNOWN; } createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(priv->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); if (!createDeviceManager) { av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); return AVERROR_UNKNOWN; } priv->d3d9 = createD3D(D3D_SDK_VERSION); if (!priv->d3d9) { av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n"); return AVERROR_UNKNOWN; } IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm); d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = 640; d3dpp.BackBufferHeight = 480; d3dpp.BackBufferCount = 0; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Flags = D3DPRESENTFLAG_VIDEO; hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, &d3dpp, &priv->d3d9device); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n"); return AVERROR_UNKNOWN; } hr = createDeviceManager(&resetToken, &hwctx->devmgr); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n"); return AVERROR_UNKNOWN; } hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n"); return AVERROR_UNKNOWN; } hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle); if (FAILED(hr)) { av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n"); return AVERROR_UNKNOWN; } return 0; }
IDirect3DDevice9 *d3dwin_open( char *title, unsigned int width_, unsigned int height_, D3DFORMAT format, BOOL fullscreen_ ){ DIRECT3DCREATE9 Direct3DCreate9; RECT rect; WNDCLASS wc; UINT32 style; D3DDISPLAYMODE displaymode; D3DPRESENT_PARAMETERS presentparameters; D3DCAPS9 caps; width = width_; height = height_; fullscreen = fullscreen_; inst = GetModuleHandle(NULL); library = (HMODULE) LoadLibrary("d3d9.dll"); if(!library) return NULL; Direct3DCreate9 = (DIRECT3DCREATE9) GetProcAddress(library,"Direct3DCreate9"); if(!Direct3DCreate9) return NULL; direct3d=Direct3DCreate9(D3D_SDK_VERSION); if(!direct3d) return NULL; if(!fullscreen) style = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU; else{ style = WS_POPUP; ShowCursor(FALSE); } rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = height; if(!fullscreen) AdjustWindowRect( &rect, style, FALSE ); wc.style = CS_VREDRAW|CS_HREDRAW; wc.lpfnWndProc = window_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = 0; wc.hIcon = LoadIcon(inst,MAKEINTRESOURCE(IDI_ICON)); wc.hCursor = LoadCursor(inst,IDC_ARROW); wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = "d3d9"; RegisterClass(&wc); win = CreateWindowEx(0, "d3d9", title, (style)|WS_VISIBLE, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0, 0, inst, 0); if(!win) return NULL; memset(&presentparameters, 0, sizeof(D3DPRESENT_PARAMETERS)); if(!fullscreen){ if(FAILED(IDirect3D9_GetAdapterDisplayMode( direct3d, D3DADAPTER_DEFAULT, &displaymode ))){ d3dwin_close(); return NULL; } } if(!fullscreen) presentparameters.Windowed = TRUE; presentparameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentparameters.BackBufferWidth = width; presentparameters.BackBufferHeight = height; if( fullscreen ) presentparameters.BackBufferFormat = format; else presentparameters.BackBufferFormat = displaymode.Format; presentparameters.AutoDepthStencilFormat = D3DFMT_D24S8; presentparameters.EnableAutoDepthStencil = TRUE; IDirect3D9_GetDeviceCaps(direct3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); if(FAILED(IDirect3D9_CreateDevice( direct3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win, (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_HARDWARE_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentparameters, &device))){ d3dwin_close(); return NULL; } IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0); IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); return device; }