static HRESULT d3d9_test_cooperative_level(void *data) { #ifndef _XBOX LPDIRECT3DDEVICE9 dev = (LPDIRECT3DDEVICE9)data; if (dev) return IDirect3DDevice9_TestCooperativeLevel(dev); #endif return E_FAIL; }
static HRESULT video_canvas_prepare_for_update(video_canvas_t *canvas) { HRESULT coopresult; if (canvas->d3ddev == NULL || canvas->d3dsurface == NULL) { return -1; } coopresult = IDirect3DDevice9_TestCooperativeLevel(canvas->d3ddev); if (coopresult == D3DERR_DEVICENOTRESET) { coopresult = video_canvas_reset_dx9(canvas); } return coopresult; }
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DSURFACE9 surface = picture->p_sys->surface; #if 0 picture_Release(picture); VLC_UNUSED(subpicture); #else /* FIXME it is a bit ugly, we need the surface to be unlocked for * rendering. * The clean way would be to release the picture (and ensure that * the vout doesn't keep a reference). But because of the vout * wrapper, we can't */ Direct3DUnlockSurface(picture); VLC_UNUSED(subpicture); #endif /* check if device is still available */ HRESULT hr = IDirect3DDevice9_TestCooperativeLevel(sys->d3ddev); if (FAILED(hr)) { if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) { vout_display_SendEventPicturesInvalid(vd); sys->reset_device = true; sys->lost_not_ready = false; } if (hr == D3DERR_DEVICELOST && !sys->lost_not_ready) { /* Device is lost but not yet ready for reset. */ sys->lost_not_ready = true; } return; } d3d_region_t picture_region; if (!Direct3DImportPicture(vd, &picture_region, surface)) { int subpicture_region_count = 0; d3d_region_t *subpicture_region = NULL; if (subpicture) Direct3DImportSubpicture(vd, &subpicture_region_count, &subpicture_region, subpicture); Direct3DRenderScene(vd, &picture_region, subpicture_region_count, subpicture_region); Direct3DDeleteRegions(sys->d3dregion_count, sys->d3dregion); sys->d3dregion_count = subpicture_region_count; sys->d3dregion = subpicture_region; } }
static void D3D_RenderPresent(SDL_Renderer * renderer) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; HRESULT result; if (!data->beginScene) { IDirect3DDevice9_EndScene(data->device); data->beginScene = SDL_TRUE; } result = IDirect3DDevice9_TestCooperativeLevel(data->device); if (result == D3DERR_DEVICELOST) { /* We'll reset later */ return; } if (result == D3DERR_DEVICENOTRESET) { D3D_Reset(renderer); } result = IDirect3DDevice9_Present(data->device, NULL, NULL, NULL, NULL); if (FAILED(result)) { D3D_SetError("Present()", result); } }
/** * It copies picture surface into a texture and renders into a scene. * * This function is intented for higher end 3D cards, with pixel shader support * and at least 64 MiB of video RAM. */ static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface) { vout_display_sys_t *sys = vd->sys; LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev; HRESULT hr; // check if device is still available hr = IDirect3DDevice9_TestCooperativeLevel(d3ddev); if (FAILED(hr)) { if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) { vout_display_SendEventPicturesInvalid(vd); sys->reset_device = true; } return; } /* */ LPDIRECT3DTEXTURE9 d3dtex = sys->d3dtex; LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc; /* Clear the backbuffer and the zbuffer */ hr = IDirect3DDevice9_Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* retrieve picture surface */ LPDIRECT3DSURFACE9 d3dsrc = surface; if (!d3dsrc) { msg_Dbg(vd, "no surface to render ?"); return; } /* retrieve texture top-level surface */ LPDIRECT3DSURFACE9 d3ddest; hr = IDirect3DTexture9_GetSurfaceLevel(d3dtex, 0, &d3ddest); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Copy picture surface into texture surface * color space conversion and scaling happen here */ RECT src = vd->sys->rect_src_clipped; RECT dst = vd->sys->rect_dest_clipped; hr = IDirect3DDevice9_StretchRect(d3ddev, d3dsrc, &src, d3ddest, &dst, D3DTEXF_LINEAR); IDirect3DSurface9_Release(d3ddest); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Update the vertex buffer */ CUSTOMVERTEX *vertices; hr = IDirect3DVertexBuffer9_Lock(d3dvtc, 0, 0, (void **)&vertices, D3DLOCK_DISCARD); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } /* Setup vertices */ const float f_width = vd->sys->d3dpp.BackBufferWidth; const float f_height = vd->sys->d3dpp.BackBufferHeight; /* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */ /* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */ vertices[0].x = -0.5f; // left vertices[0].y = -0.5f; // top vertices[0].z = 0.0f; vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[0].rhw = 1.0f; vertices[0].tu = 0.0f; vertices[0].tv = 0.0f; vertices[1].x = f_width - 0.5f; // right vertices[1].y = -0.5f; // top vertices[1].z = 0.0f; vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[1].rhw = 1.0f; vertices[1].tu = 1.0f; vertices[1].tv = 0.0f; vertices[2].x = f_width - 0.5f; // right vertices[2].y = f_height - 0.5f; // bottom vertices[2].z = 0.0f; vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[2].rhw = 1.0f; vertices[2].tu = 1.0f; vertices[2].tv = 1.0f; vertices[3].x = -0.5f; // left vertices[3].y = f_height - 0.5f; // bottom vertices[3].z = 0.0f; vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255); vertices[3].rhw = 1.0f; vertices[3].tu = 0.0f; vertices[3].tv = 1.0f; hr= IDirect3DVertexBuffer9_Unlock(d3dvtc); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } // Begin the scene hr = IDirect3DDevice9_BeginScene(d3ddev); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } // Setup our texture. Using textures introduces the texture stage states, // which govern how textures get blended together (in the case of multiple // textures) and lighting information. In this case, we are modulating // (blending) our texture with the diffuse color of the vertices. hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // Render the vertex buffer contents hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX)); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // we use FVF instead of vertex shader hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // draw rectangle hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); IDirect3DDevice9_EndScene(d3ddev); return; } // End the scene hr = IDirect3DDevice9_EndScene(d3ddev); if (FAILED(hr)) { msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr); return; } }
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); }