summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/d3d11/context.c7
-rw-r--r--video/out/d3d11/ra_d3d11.c57
-rw-r--r--video/out/gpu/d3d11_helpers.c81
-rw-r--r--video/out/gpu/d3d11_helpers.h2
-rw-r--r--video/out/opengl/context_angle.c12
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 = {