/** \fn displayImage_argb \brief manually do the yv12-> RGB conversion + rescale and the upload to backbuffer */ bool dxvaRender::displayImage_argb(ADMImage *pic) { IDirect3DSurface9 *bBuffer; // 1 upload to myYV12 surface if( ADM_FAILED(IDirect3DDevice9_GetBackBuffer(d3dDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &bBuffer))) { ADM_warning("D3D Cannot create backBuffer\n"); return false; } if(!ADMImage_To_argbSurface(pic,bBuffer,scaler)) { ADM_warning("Image to argb surface failed\n"); return false; } IDirect3DDevice9_BeginScene(d3dDevice); IDirect3DDevice9_EndScene(d3dDevice); if( ADM_FAILED(IDirect3DDevice9_Present(d3dDevice, &targetRect, 0, 0, 0))) { ADM_warning("D3D Present failed\n"); } return true; }
/** \fn brief input is already a surface, in yv12 format */ bool dxvaRender::displayImage_surface(ADMImage *pic,admDx2Surface *surface) { // this does not work, both surfaces are coming from different device IDirect3DSurface9 *bBuffer; POINT point={0,0}; // 1 upload to myYV12 surface if(ADM_FAILED(IDirect3DDevice9_UpdateSurface(d3dDevice, surface->surface, // src &panScan, // src rect myYV12Surface, // dst &point // where to ))) { ADM_warning("Copying surface failed, switching to non accelerated path \n"); if(!pic->hwDownloadFromRef()) { ADM_warning("Failed to download yv12 from dxva\n"); return false; } // workaround : use default non bridged path if(useYV12) { return displayImage_yv12(pic); } return displayImage_argb(pic); return false; } // upload.... if( ADM_FAILED(IDirect3DDevice9_GetBackBuffer(d3dDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &bBuffer))) { ADM_warning("D3D Cannot create backBuffer\n"); return false; } // data are in YV12 surface, blit it to mySurface // zoom and color conversion happen there if (ADM_FAILED(IDirect3DDevice9_StretchRect(d3dDevice, myYV12Surface, NULL, bBuffer, NULL, D3DTEXF_LINEAR))) { ADM_warning("StretchRec yv12 failed\n"); } IDirect3DDevice9_BeginScene(d3dDevice); IDirect3DDevice9_EndScene(d3dDevice); if( ADM_FAILED(IDirect3DDevice9_Present(d3dDevice, &targetRect, 0, 0, 0))) { ADM_warning("D3D Present failed\n"); } return true; }
static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, Uint32 format, void * pixels, int pitch) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; D3DSURFACE_DESC desc; LPDIRECT3DSURFACE9 backBuffer; LPDIRECT3DSURFACE9 surface; RECT d3drect; D3DLOCKED_RECT locked; HRESULT result; result = IDirect3DDevice9_GetBackBuffer(data->device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); if (FAILED(result)) { return D3D_SetError("GetBackBuffer()", result); } result = IDirect3DSurface9_GetDesc(backBuffer, &desc); if (FAILED(result)) { IDirect3DSurface9_Release(backBuffer); return D3D_SetError("GetDesc()", result); } result = IDirect3DDevice9_CreateOffscreenPlainSurface(data->device, desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, NULL); if (FAILED(result)) { IDirect3DSurface9_Release(backBuffer); return D3D_SetError("CreateOffscreenPlainSurface()", result); } result = IDirect3DDevice9_GetRenderTargetData(data->device, backBuffer, surface); if (FAILED(result)) { IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return D3D_SetError("GetRenderTargetData()", result); } d3drect.left = rect->x; d3drect.right = rect->x + rect->w; d3drect.top = rect->y; d3drect.bottom = rect->y + rect->h; result = IDirect3DSurface9_LockRect(surface, &locked, &d3drect, D3DLOCK_READONLY); if (FAILED(result)) { IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return D3D_SetError("LockRect()", result); } SDL_ConvertPixels(rect->w, rect->h, D3DFMTToPixelFormat(desc.Format), locked.pBits, locked.Pitch, format, pixels, pitch); IDirect3DSurface9_UnlockRect(surface); IDirect3DSurface9_Release(surface); IDirect3DSurface9_Release(backBuffer); return 0; }
/** \fn displayImage_yv12 \brief copy image to myV12 surface then convert from yv12 to display format in mySurface */ bool dxvaRender::displayImage_yv12(ADMImage *pic) { IDirect3DSurface9 *bBuffer; // 1 upload to myYV12 surface if(!ADMImage_To_yv12Surface(pic,myYV12Surface)) { return false; } // upload.... if( ADM_FAILED(IDirect3DDevice9_GetBackBuffer(d3dDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &bBuffer))) { ADM_warning("D3D Cannot create backBuffer\n"); return false; } // data are in YV12 surface, blit it to mySurface // zoom and color conversion happen there if (ADM_FAILED(IDirect3DDevice9_StretchRect(d3dDevice, myYV12Surface, NULL, bBuffer, NULL, D3DTEXF_LINEAR))) { ADM_warning("StretchRec yv12 failed\n"); } IDirect3DDevice9_BeginScene(d3dDevice); IDirect3DDevice9_EndScene(d3dDevice); if( ADM_FAILED(IDirect3DDevice9_Present(d3dDevice, &targetRect, 0, 0, 0))) { ADM_warning("D3D Present failed\n"); } return true; }
/** @brief Create D3D Offscreen and Backbuffer surfaces. Each * surface is created only if it's not already present. * @return 1 on success, 0 on failure */ static int create_d3d_surfaces(void) { int osd_width = vo_dwidth, osd_height = vo_dheight; int tex_width = osd_width, tex_height = osd_height; mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>create_d3d_surfaces called.\n"); if (!priv->d3d_surface && FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface( priv->d3d_device, priv->src_width, priv->src_height, priv->movie_src_fmt, D3DPOOL_DEFAULT, &priv->d3d_surface, NULL))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating offscreen surface failed.\n"); return 0; } if (!priv->d3d_backbuf && FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &priv->d3d_backbuf))) { mp_msg(MSGT_VO, MSGL_ERR, "<vo_direct3d>Allocating backbuffer failed.\n"); return 0; } /* calculate the best size for the OSD depending on the factors from the device */ if (priv->device_caps_power2_only) { tex_width = 1; tex_height = 1; while (tex_width < osd_width ) tex_width <<= 1; while (tex_height < osd_height) tex_height <<= 1; } if (priv->device_caps_square_only) /* device only supports square textures */ tex_width = tex_height = tex_width > tex_height ? tex_width : tex_height; // better round up to a multiple of 16 tex_width = (tex_width + 15) & ~15; tex_height = (tex_height + 15) & ~15; // make sure we respect the size limits without breaking aspect or pow2-requirements while (tex_width > priv->max_texture_width || tex_height > priv->max_texture_height) { osd_width >>= 1; osd_height >>= 1; tex_width >>= 1; tex_height >>= 1; } priv->osd_width = osd_width; priv->osd_height = osd_height; priv->osd_texture_width = tex_width; priv->osd_texture_height = tex_height; mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>OSD texture size (%dx%d), requested (%dx%d).\n", vo_dwidth, vo_dheight, priv->osd_texture_width, priv->osd_texture_height); /* create OSD */ if (!priv->d3d_texture_system && FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, priv->osd_texture_width, priv->osd_texture_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8L8, D3DPOOL_SYSTEMMEM, &priv->d3d_texture_system, NULL))) { mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>Allocating OSD texture in system RAM failed.\n"); return 0; } if (!priv->device_texture_sys) { /* only create if we need a shadow version on the external device */ if (!priv->d3d_texture_osd && FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, priv->osd_texture_width, priv->osd_texture_height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8L8, D3DPOOL_DEFAULT, &priv->d3d_texture_osd, NULL))) { mp_msg(MSGT_VO,MSGL_ERR, "<vo_direct3d>Allocating OSD texture in video RAM failed.\n"); return 0; } } /* setup default renderstate */ IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_SRCBLEND, D3DBLEND_ONE); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAREF, (DWORD)0x0); IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_LIGHTING, FALSE); IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); return 1; }
int video_canvas_refresh_dx9(video_canvas_t *canvas, unsigned int xs, unsigned int ys, unsigned int xi, unsigned int yi, unsigned int w, unsigned int h) { HRESULT stretchresult; LPDIRECT3DSURFACE9 d3dbackbuffer = NULL; D3DLOCKED_RECT lockedrect; if (canvas->videoconfig->doublesizex) { xi *= (canvas->videoconfig->doublesizex + 1); w *= (canvas->videoconfig->doublesizex + 1); } if (canvas->videoconfig->doublesizey) { yi *= (canvas->videoconfig->doublesizey + 1); h *= (canvas->videoconfig->doublesizey + 1); } if (S_OK != video_canvas_prepare_for_update(canvas)) { return -1; } if (S_OK != IDirect3DDevice9_Clear(canvas->d3ddev, 0, NULL, D3DCLEAR_TARGET, 0, 0, 0) || S_OK != IDirect3DDevice9_BeginScene(canvas->d3ddev) || S_OK != IDirect3DDevice9_GetBackBuffer(canvas->d3ddev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &d3dbackbuffer) || S_OK != IDirect3DSurface9_LockRect(canvas->d3dsurface, &lockedrect, NULL, 0)) { log_debug("video_dx9: Failed to prepare for rendering!"); return -1; } video_canvas_render(canvas, lockedrect.pBits, w, h, xs, ys, xi, yi, lockedrect.Pitch, 32); //video_save_screen ("c:\\temp\\screens\\", w, h, 32, lockedrect.pBits); if (S_OK != IDirect3DSurface9_UnlockRect(canvas->d3dsurface)) { log_debug("video_dx9: Failed to unlock surface!"); return -1; } do { stretchresult = IDirect3DDevice9_StretchRect(canvas->d3ddev, canvas->d3dsurface, NULL, d3dbackbuffer, canvas->dest_rect_ptr, d3dpreffilter); if (d3dpreffilter == D3DTEXF_NONE) { break; } if (stretchresult != S_OK) { /* Some adapters don't support filtering */ d3dpreffilter = D3DTEXF_NONE; log_debug("video_dx9: Disabled StretchRect filtering!"); } } while (stretchresult != S_OK); if (stretchresult != S_OK) { log_debug("video_dx9: StretchRect failed even without filtering!"); } if (S_OK != IDirect3DSurface9_Release(d3dbackbuffer) || S_OK != IDirect3DDevice9_EndScene(canvas->d3ddev)) { log_debug("video_dx9: EndScene failed!"); return -1; } if (S_OK != IDirect3DDevice9_Present(canvas->d3ddev, NULL, NULL, NULL, NULL)) { log_debug("video_dx9: Refresh failed to present the scene!"); return -1; } return 0; }
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 }