diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/out/d3d11/context.c | 7 | ||||
-rw-r--r-- | video/out/d3d11/ra_d3d11.c | 57 | ||||
-rw-r--r-- | video/out/gpu/d3d11_helpers.c | 81 | ||||
-rw-r--r-- | video/out/gpu/d3d11_helpers.h | 2 | ||||
-rw-r--r-- | video/out/opengl/context_angle.c | 12 |
5 files changed, 57 insertions, 102 deletions
diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c index af664d9988..82c7d162f7 100644 --- a/video/out/d3d11/context.c +++ b/video/out/d3d11/context.c @@ -70,12 +70,6 @@ struct priv { IDXGISwapChain *swapchain; }; -static struct mp_image *d3d11_screenshot(struct ra_swapchain *sw) -{ - struct priv *p = sw->ctx->priv; - return mp_d3d11_screenshot(p->swapchain); -} - static struct ra_tex *get_backbuffer(struct ra_ctx *ctx) { struct priv *p = ctx->priv; @@ -179,7 +173,6 @@ static void d3d11_uninit(struct ra_ctx *ctx) static const struct ra_swapchain_fns d3d11_swapchain = { .color_depth = d3d11_color_depth, - .screenshot = d3d11_screenshot, .start_frame = d3d11_start_frame, .submit_frame = d3d11_submit_frame, .swap_buffers = d3d11_swap_buffers, diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c index bf2657b6f6..1d2455853b 100644 --- a/video/out/d3d11/ra_d3d11.c +++ b/video/out/d3d11/ra_d3d11.c @@ -78,6 +78,9 @@ struct d3d_tex { ID3D11Texture3D *tex3d; int array_slice; + // Staging texture for tex_download(), 2D only + ID3D11Texture2D *staging; + ID3D11ShaderResourceView *srv; ID3D11RenderTargetView *rtv; ID3D11UnorderedAccessView *uav; @@ -359,12 +362,17 @@ static void tex_destroy(struct ra *ra, struct ra_tex *tex) SAFE_RELEASE(tex_p->uav); SAFE_RELEASE(tex_p->sampler); SAFE_RELEASE(tex_p->res); + SAFE_RELEASE(tex_p->staging); talloc_free(tex); } static struct ra_tex *tex_create(struct ra *ra, const struct ra_tex_params *params) { + // Only 2D textures may be downloaded for now + if (params->downloadable && params->dimensions != 2) + return NULL; + struct ra_d3d11 *p = ra->priv; HRESULT hr; @@ -437,6 +445,21 @@ static struct ra_tex *tex_create(struct ra *ra, goto error; } tex_p->res = (ID3D11Resource *)tex_p->tex2d; + + // Create a staging texture with CPU access for tex_download() + if (params->downloadable) { + desc2d.BindFlags = 0; + desc2d.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc2d.Usage = D3D11_USAGE_STAGING; + + hr = ID3D11Device_CreateTexture2D(p->dev, &desc2d, NULL, + &tex_p->staging); + if (FAILED(hr)) { + MP_ERR(ra, "Failed to staging texture: %s\n", + mp_HRESULT_to_str(hr)); + goto error; + } + } break; case 3:; D3D11_TEXTURE3D_DESC desc3d = { @@ -652,6 +675,39 @@ static bool tex_upload(struct ra *ra, const struct ra_tex_upload_params *params) return true; } +static bool tex_download(struct ra *ra, struct ra_tex_download_params *params) +{ + struct ra_d3d11 *p = ra->priv; + struct ra_tex *tex = params->tex; + struct d3d_tex *tex_p = tex->priv; + HRESULT hr; + + if (!tex_p->staging) + return false; + + ID3D11DeviceContext_CopyResource(p->ctx, (ID3D11Resource*)tex_p->staging, + tex_p->res); + + D3D11_MAPPED_SUBRESOURCE lock; + hr = ID3D11DeviceContext_Map(p->ctx, (ID3D11Resource*)tex_p->staging, 0, + D3D11_MAP_READ, 0, &lock); + if (FAILED(hr)) { + MP_ERR(ra, "Failed to map staging texture: %s\n", mp_HRESULT_to_str(hr)); + return false; + } + + char *cdst = params->dst; + char *csrc = lock.pData; + for (int y = 0; y < tex->params.h; y++) { + memcpy(cdst + y * params->stride, csrc + y * lock.RowPitch, + MPMIN(params->stride, lock.RowPitch)); + } + + ID3D11DeviceContext_Unmap(p->ctx, (ID3D11Resource*)tex_p->staging, 0); + + return true; +} + static void buf_destroy(struct ra *ra, struct ra_buf *buf) { if (!buf) @@ -2045,6 +2101,7 @@ static struct ra_fns ra_fns_d3d11 = { .tex_create = tex_create, .tex_destroy = tex_destroy, .tex_upload = tex_upload, + .tex_download = tex_download, .buf_create = buf_create, .buf_destroy = buf_destroy, .buf_update = buf_update, diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c index 7bdd3c2eaa..d267ac3009 100644 --- a/video/out/gpu/d3d11_helpers.c +++ b/video/out/gpu/d3d11_helpers.c @@ -374,84 +374,3 @@ done: SAFE_RELEASE(dxgi_dev); return success; } - -struct mp_image *mp_d3d11_screenshot(IDXGISwapChain *swapchain) -{ - ID3D11Device *dev = NULL; - ID3D11DeviceContext *ctx = NULL; - ID3D11Texture2D *frontbuffer = NULL; - ID3D11Texture2D *staging = NULL; - struct mp_image *img = NULL; - HRESULT hr; - - // Validate the swap chain. This screenshot method will only work on DXGI - // 1.2+ flip/sequential swap chains. It's probably not possible at all with - // discard swap chains, since by definition, the backbuffer contents is - // discarded on Present(). - DXGI_SWAP_CHAIN_DESC scd; - hr = IDXGISwapChain_GetDesc(swapchain, &scd); - if (FAILED(hr)) - goto done; - if (scd.SwapEffect != DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) - goto done; - - // Get the last buffer that was presented with Present(). This should be - // the n-1th buffer for a swap chain of length n. - hr = IDXGISwapChain_GetBuffer(swapchain, scd.BufferCount - 1, - &IID_ID3D11Texture2D, (void**)&frontbuffer); - if (FAILED(hr)) - goto done; - - ID3D11Texture2D_GetDevice(frontbuffer, &dev); - ID3D11Device_GetImmediateContext(dev, &ctx); - - D3D11_TEXTURE2D_DESC td; - ID3D11Texture2D_GetDesc(frontbuffer, &td); - if (td.SampleDesc.Count > 1) - goto done; - - // Validate the backbuffer format and convert to an mpv IMGFMT - enum mp_imgfmt fmt; - switch (td.Format) { - case DXGI_FORMAT_B8G8R8A8_UNORM: fmt = IMGFMT_BGR0; break; - case DXGI_FORMAT_R8G8B8A8_UNORM: fmt = IMGFMT_RGB0; break; - default: - goto done; - } - - // Create a staging texture based on the frontbuffer with CPU access - td.BindFlags = 0; - td.MiscFlags = 0; - td.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - td.Usage = D3D11_USAGE_STAGING; - hr = ID3D11Device_CreateTexture2D(dev, &td, 0, &staging); - if (FAILED(hr)) - goto done; - - ID3D11DeviceContext_CopyResource(ctx, (ID3D11Resource*)staging, - (ID3D11Resource*)frontbuffer); - - // Attempt to map the staging texture to CPU-accessible memory - D3D11_MAPPED_SUBRESOURCE lock; - hr = ID3D11DeviceContext_Map(ctx, (ID3D11Resource*)staging, 0, - D3D11_MAP_READ, 0, &lock); - if (FAILED(hr)) - goto done; - - img = mp_image_alloc(fmt, td.Width, td.Height); - if (!img) - return NULL; - for (int i = 0; i < td.Height; i++) { - memcpy(img->planes[0] + img->stride[0] * i, - (char*)lock.pData + lock.RowPitch * i, td.Width * 4); - } - - ID3D11DeviceContext_Unmap(ctx, (ID3D11Resource*)staging, 0); - -done: - SAFE_RELEASE(frontbuffer); - SAFE_RELEASE(staging); - SAFE_RELEASE(ctx); - SAFE_RELEASE(dev); - return img; -} diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h index 481c183b4d..996b93494f 100644 --- a/video/out/gpu/d3d11_helpers.h +++ b/video/out/gpu/d3d11_helpers.h @@ -78,6 +78,4 @@ bool mp_d3d11_create_swapchain(ID3D11Device *dev, struct mp_log *log, struct d3d11_swapchain_opts *opts, IDXGISwapChain **swapchain_out); -struct mp_image *mp_d3d11_screenshot(IDXGISwapChain *swapchain); - #endif diff --git a/video/out/opengl/context_angle.c b/video/out/opengl/context_angle.c index 986a50362b..6d45e29496 100644 --- a/video/out/opengl/context_angle.c +++ b/video/out/opengl/context_angle.c @@ -525,17 +525,6 @@ static int angle_color_depth(struct ra_swapchain *sw) return 8; } -static struct mp_image *angle_screenshot(struct ra_swapchain *sw) -{ - struct priv *p = sw->ctx->priv; - if (p->dxgi_swapchain) { - struct mp_image *img = mp_d3d11_screenshot(p->dxgi_swapchain); - if (img) - return img; - } - return ra_gl_ctx_screenshot(sw); -} - static bool angle_submit_frame(struct ra_swapchain *sw, const struct vo_frame *frame) { @@ -611,7 +600,6 @@ static bool angle_init(struct ra_ctx *ctx) // Custom swapchain impl for the D3D11 swapchain-based surface static const struct ra_swapchain_fns dxgi_swapchain_fns = { .color_depth = angle_color_depth, - .screenshot = angle_screenshot, .submit_frame = angle_submit_frame, }; struct ra_gl_ctx_params params = { |