summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ross-Gowan <rossy@jrg.systems>2017-10-11 18:10:39 +1100
committerJames Ross-Gowan <rossy@jrg.systems>2017-11-07 20:27:13 +1100
commit4b014b3a8125de22350748d97171c63041256d7b (patch)
treeaeb0b408a3cc6792fb92d6c6a697f98937499dbf
parent9b2dae79b1be1f57e7b6bcf80d500ab4190aa3d3 (diff)
downloadmpv-4b014b3a8125de22350748d97171c63041256d7b.tar.bz2
mpv-4b014b3a8125de22350748d97171c63041256d7b.tar.xz
vo_gpu: move d3d11_screenshot to shared code
This can be used by the ANGLE backend and ra_d3d11.
-rw-r--r--video/out/d3d11/context.c9
-rw-r--r--video/out/gpu/d3d11_helpers.c81
-rw-r--r--video/out/gpu/d3d11_helpers.h4
-rw-r--r--video/out/opengl/context_angle.c86
4 files changed, 100 insertions, 80 deletions
diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c
index 018fd99934..b02d2e80ce 100644
--- a/video/out/d3d11/context.c
+++ b/video/out/d3d11/context.c
@@ -70,6 +70,14 @@ struct priv {
IDXGISwapChain *swapchain;
};
+static struct mp_image *d3d11_screenshot(struct ra_swapchain *sw)
+{
+ struct priv *p = sw->ctx->priv;
+ if (!p->swapchain)
+ return NULL;
+ return mp_d3d11_screenshot(p->swapchain);
+}
+
static struct ra_tex *get_backbuffer(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -169,6 +177,7 @@ 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/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c
index 7912a8c23a..6391ed92cd 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -399,3 +399,84 @@ 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 6d99c62a51..481c183b4d 100644
--- a/video/out/gpu/d3d11_helpers.h
+++ b/video/out/gpu/d3d11_helpers.h
@@ -23,6 +23,8 @@
#include <d3d11.h>
#include <dxgi1_2.h>
+#include "video/mp_image.h"
+
#define D3D_FEATURE_LEVEL_12_0 (0xc000)
#define D3D_FEATURE_LEVEL_12_1 (0xc100)
@@ -76,4 +78,6 @@ 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 b504293db5..986a50362b 100644
--- a/video/out/opengl/context_angle.c
+++ b/video/out/opengl/context_angle.c
@@ -518,83 +518,6 @@ static void angle_swap_buffers(struct ra_ctx *ctx)
egl_swap_buffers(ctx);
}
-static struct mp_image *d3d11_screenshot(struct ra_ctx *ctx)
-{
- struct priv *p = ctx->priv;
- ID3D11Texture2D *frontbuffer = NULL;
- ID3D11Texture2D *staging = NULL;
- struct mp_image *img = NULL;
- HRESULT hr;
-
- if (!p->dxgi_swapchain)
- goto done;
-
- // 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(p->dxgi_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(p->dxgi_swapchain, scd.BufferCount - 1,
- &IID_ID3D11Texture2D, (void**)&frontbuffer);
- if (FAILED(hr))
- goto done;
-
- 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(p->d3d11_device, &td, 0, &staging);
- if (FAILED(hr))
- goto done;
-
- ID3D11DeviceContext_CopyResource(p->d3d11_context,
- (ID3D11Resource*)staging, (ID3D11Resource*)frontbuffer);
-
- // Attempt to map the staging texture to CPU-accessible memory
- D3D11_MAPPED_SUBRESOURCE lock;
- hr = ID3D11DeviceContext_Map(p->d3d11_context, (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(p->d3d11_context, (ID3D11Resource*)staging, 0);
-
-done:
- SAFE_RELEASE(frontbuffer);
- SAFE_RELEASE(staging);
- return img;
-}
static int angle_color_depth(struct ra_swapchain *sw)
{
@@ -604,9 +527,12 @@ static int angle_color_depth(struct ra_swapchain *sw)
static struct mp_image *angle_screenshot(struct ra_swapchain *sw)
{
- struct mp_image *img = d3d11_screenshot(sw->ctx);
- if (img)
- return img;
+ 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);
}