From f68eb7c108bc38eba2b947c6c557f952c2c50895 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Wed, 22 Jan 2025 23:28:09 +0700 Subject: [PATCH] #511 upload pixel data with memcpy then CopyResource I have tried hard to use the CPU buffer directly as it is, but can't seem to be able to map it properly so that CopyResource will accept it --- xpra/codecs/amf/amf.pxd | 25 ++++ xpra/codecs/amf/common.pxd | 4 +- xpra/codecs/amf/common.pyx | 28 ++++- xpra/codecs/amf/encoder.pyx | 94 +++++++++------ xpra/platform/win32/d3d11/device.pyx | 170 ++++++++++++++++++++++++--- 5 files changed, 264 insertions(+), 57 deletions(-) diff --git a/xpra/codecs/amf/amf.pxd b/xpra/codecs/amf/amf.pxd index 4a12a319e4..b589f85052 100644 --- a/xpra/codecs/amf/amf.pxd +++ b/xpra/codecs/amf/amf.pxd @@ -92,6 +92,23 @@ cdef extern from "core/Result.h": AMF_VULKAN_FAILED +cdef inline MEMORY_TYPE_STR(AMF_MEMORY_TYPE memory): + return { + AMF_MEMORY_UNKNOWN: "UNKNOWN", + AMF_MEMORY_HOST: "HOST", + AMF_MEMORY_DX9: "DX9", + AMF_MEMORY_DX11: "DX11", + AMF_MEMORY_OPENCL: "OPENCL", + AMF_MEMORY_OPENGL: "OPENGL", + AMF_MEMORY_XV: "XV", + AMF_MEMORY_GRALLOC: "GRALLOC", + AMF_MEMORY_COMPUTE_FOR_DX9: "COMPUTE_FOR_DX9", + AMF_MEMORY_COMPUTE_FOR_DX11: "COMPUTE_FOR_DX11", + AMF_MEMORY_VULKAN: "VULKAN", + AMF_MEMORY_DX12: "DX12", + }.get(memory, "unknown") + + cdef inline RESULT_STR(AMF_RESULT res): return { AMF_OK: "OK", @@ -170,6 +187,8 @@ cdef extern from "core/Data.h": ctypedef amf_size (*DATA_GETPROPERTYCOUNT)(AMFData* pThis) ctypedef AMF_MEMORY_TYPE (*DATA_GETMEMORYTYPE)(AMFData* pThis) ctypedef AMF_DATA_TYPE (*DATA_GETDATATYPE)(AMFData* pThis) + ctypedef AMF_RESULT (*DATA_CONVERT)(AMFData* pThis, AMF_MEMORY_TYPE type) + ctypedef AMF_RESULT (*DATA_INTEROP)(AMFData* pThis, AMF_MEMORY_TYPE type) ctypedef struct AMFDataVtbl: DATA_ACQUIRE Acquire @@ -178,6 +197,8 @@ cdef extern from "core/Data.h": DATA_GETPROPERTYCOUNT GetPropertyCount DATA_GETMEMORYTYPE GetMemoryType DATA_GETDATATYPE GetDataType + DATA_CONVERT Convert + DATA_INTEROP Interop ctypedef struct AMFData: const AMFDataVtbl *pVtbl @@ -433,6 +454,8 @@ cdef extern from "core/Surface.h": ctypedef AMFPlane* (*SURFACE_GETPLANEAT)(AMFSurface* pThis, amf_size index) ctypedef AMFPlane* (*SURFACE_GETPLANE)(AMFSurface* pThis, AMF_PLANE_TYPE type) ctypedef AMF_FRAME_TYPE (*SURFACE_GETFRAMETYPE)(AMFSurface* pThis) + ctypedef AMF_RESULT (*SURFACE_CONVERT)(AMFSurface* pThis, AMF_MEMORY_TYPE type) + ctypedef AMF_RESULT (*SURFACE_INTEROP)(AMFSurface* pThis, AMF_MEMORY_TYPE type) ctypedef struct AMFSurfaceVtbl: SURFACE_SETPROPERTY SetProperty @@ -443,6 +466,8 @@ cdef extern from "core/Surface.h": SURFACE_GETPLANEAT GetPlaneAt SURFACE_GETPLANE GetPlane SURFACE_GETFRAMETYPE GetFrameType + SURFACE_CONVERT Convert + SURFACE_INTEROP Interop ctypedef struct AMFSurface: const AMFSurfaceVtbl *pVtbl diff --git a/xpra/codecs/amf/common.pxd b/xpra/codecs/amf/common.pxd index 0f9555ed2c..16864d3c70 100644 --- a/xpra/codecs/amf/common.pxd +++ b/xpra/codecs/amf/common.pxd @@ -7,7 +7,7 @@ from libc.stddef cimport wchar_t from libc.stdint cimport uint64_t, uintptr_t from xpra.codecs.amf.amf cimport ( - AMF_RESULT, AMFFactory, AMFGuid, + AMF_RESULT, AMFFactory, AMFGuid, AMFSurface, amf_uint32, amf_uint16, amf_uint8, ) @@ -25,3 +25,5 @@ cdef void set_guid(AMFGuid *guid, amf_uint8 _data45, amf_uint8 _data46, amf_uint8 _data47, amf_uint8 _data48) cdef uint64_t get_c_version() + +cdef void fill_nv12_surface(AMFSurface *surface, amf_uint8 Y, amf_uint8 U, amf_uint8 V) diff --git a/xpra/codecs/amf/common.pyx b/xpra/codecs/amf/common.pyx index ddcd935616..71a2668ec7 100644 --- a/xpra/codecs/amf/common.pyx +++ b/xpra/codecs/amf/common.pyx @@ -7,11 +7,12 @@ from ctypes import CDLL, c_uint64, c_int, c_void_p, byref, POINTER from libc.stddef cimport wchar_t from libc.stdint cimport uint64_t, uintptr_t +from libc.string cimport memset from xpra.codecs.amf.amf cimport ( AMF_RESULT, AMF_OK, - AMFFactory, AMFGuid, AMFTrace, - amf_uint32, amf_uint16, amf_uint8, + AMFFactory, AMFGuid, AMFTrace, AMFSurface, AMFPlane, + amf_uint32, amf_uint16, amf_uint8, amf_int32, RESULT_STR, ) @@ -121,3 +122,26 @@ cdef uint64_t get_c_version(): return 0 return int(version.value) + +cdef void fill_nv12_surface(AMFSurface *surface, amf_uint8 Y, amf_uint8 U, amf_uint8 V): + cdef AMFPlane *planeY = surface.pVtbl.GetPlaneAt(surface, 0) + cdef amf_int32 widthY = planeY.pVtbl.GetWidth(planeY) + cdef amf_int32 heightY = planeY.pVtbl.GetHeight(planeY) + cdef amf_int32 lineY = planeY.pVtbl.GetHPitch(planeY) + cdef amf_uint8 *Ydata = planeY.pVtbl.GetNative(planeY) + cdef amf_int32 y + cdef amf_uint8 *line + for y in range(heightY): + line = Ydata + y * lineY + memset(line, Y, widthY) + cdef AMFPlane *planeUV = surface.pVtbl.GetPlaneAt(surface, 1) + cdef amf_int32 widthUV = planeUV.pVtbl.GetWidth(planeUV) + cdef amf_int32 heightUV = planeUV.pVtbl.GetHeight(planeUV) + cdef amf_int32 lineUV = planeUV.pVtbl.GetHPitch(planeUV) + cdef amf_uint8 *UVdata = planeUV.pVtbl.GetNative(planeUV) + cdef amf_int32 x + for y in range(heightUV): + line = UVdata + y * lineUV + for x in range(widthUV): + line[x] = U + line[x+1] = V diff --git a/xpra/codecs/amf/encoder.pyx b/xpra/codecs/amf/encoder.pyx index e2bafb9d28..4283227ecc 100644 --- a/xpra/codecs/amf/encoder.pyx +++ b/xpra/codecs/amf/encoder.pyx @@ -20,15 +20,14 @@ from xpra.log import Logger from libc.stddef cimport wchar_t from libc.stdint cimport uint8_t, int64_t, uintptr_t -from libc.string cimport memset +from libc.string cimport memset, memcpy from xpra.codecs.amf.amf cimport ( - AMF_PLANE_TYPE_STR, AMF_SURFACE_FORMAT_STR, - AMF_FRAME_TYPE, AMF_FRAME_TYPE_STR, + amf_uint8, + AMF_PLANE_TYPE_STR, AMF_SURFACE_FORMAT_STR, AMF_FRAME_TYPE, AMF_FRAME_TYPE_STR, MEMORY_TYPE_STR, AMF_RESULT, AMF_EOF, AMF_REPEAT, AMF_DX11_0, - AMF_MEMORY_TYPE, - AMF_MEMORY_DX11, + AMF_MEMORY_TYPE, AMF_MEMORY_DX11, AMF_MEMORY_HOST, AMF_INPUT_FULL, AMF_SURFACE_FORMAT, AMF_SURFACE_YUV420P, AMF_SURFACE_NV12, AMF_SURFACE_BGRA, AMF_VARIANT_TYPE, AMF_VARIANT_INT64, AMF_VARIANT_SIZE, AMF_VARIANT_RATE, @@ -230,11 +229,9 @@ cdef class Encoder: self.context = NULL self.encoder = NULL - self.surface = NULL self.device = NULL self.amf_context_init() - self.amf_surface_init() self.amf_encoder_init(options) self.generation = generation.increase() @@ -273,13 +270,6 @@ cdef class Encoder: self.device = self.context.pVtbl.GetOpenGLContext(self.context) log(f"amf_context_init() device=%#x", self.device) - def amf_surface_init(self) -> None: - assert DX11 - cdef AMF_MEMORY_TYPE memory = AMF_MEMORY_DX11 - cdef AMF_RESULT res = self.context.pVtbl.AllocSurface(self.context, memory, self.surface_format, self.width, self.height, &self.surface) - self.check(res, "AMF surface initialization for {self.width}x{self.height} {self.src_format}") - log(f"amf_surface_init() surface=%s", self.get_surface_info(self.surface)) - cdef void set_encoder_property(self, name: str, AMFVariantStruct var): cdef wchar_t *prop = PyUnicode_AsWideCharString(name, NULL) ret = self.encoder.pVtbl.SetProperty(self.encoder, prop, var) @@ -403,11 +393,6 @@ cdef class Encoder: self.clean() def clean(self) -> None: - log("clean() surface=%s", self.surface) - cdef AMFSurface* surface = self.surface - if surface: - self.surface = NULL - surface.pVtbl.Release(surface) log("clean() encoder=%s", self.encoder) cdef AMFComponent* encoder = self.encoder if encoder: @@ -479,17 +464,42 @@ cdef class Encoder: if py_buf[i].buf: PyBuffer_Release(&py_buf[i]) - cdef void set_surface_property(self, name: str, variant: AMF_VARIANT_TYPE, value: int64_t): + cdef void alloc_surface(self, AMFSurface **surface, AMF_MEMORY_TYPE memory=AMF_MEMORY_HOST): + assert self.context + memtype = MEMORY_TYPE_STR(memory) + cdef AMF_RESULT res = self.context.pVtbl.AllocSurface(self.context, memory, self.surface_format, + self.width, self.height, surface) + if res: + self.check(res, f"AMF {memtype} surface initialization for {self.width}x{self.height} {self.src_format}") + cdef AMFSurface *ptr = surface[0] + assert ptr != NULL + log(f"{memtype} surface: %s", self.get_surface_info(ptr)) + + cdef void set_surface_property(self, AMFSurface *surface, name: str, variant: AMF_VARIANT_TYPE, value: int64_t): cdef AMFVariantStruct var AMFVariantAssignInt64(&var, value) cdef wchar_t *prop = PyUnicode_AsWideCharString(name, NULL) - self.surface.pVtbl.SetProperty(self.surface, prop, var) + surface.pVtbl.SetProperty(surface, prop, var) PyMem_Free(prop) + cdef uintptr_t get_native_plane(self, AMFSurface *surface, unsigned int plane_index): + # get the D3D11 host destination surface pointer for this plane: + plane = surface.pVtbl.GetPlaneAt(surface, plane_index) + assert plane + log("plane=%s", self.get_plane_info(plane)) + # texture is a `ID3D11Texture2D`: + cdef uintptr_t texture = plane.pVtbl.GetNative(plane) + assert texture + return texture + cdef bytes do_compress_image(self, uint8_t *pic_in[2], int strides[2]): cdef unsigned long start_time = 0 # nanoseconds! cdef AMFPlane *plane - cdef uintptr_t dst_texture + cdef uintptr_t host_texture + cdef uintptr_t gpu_texture + cdef AMFSurface *host_surface + cdef AMFSurface *gpu_surface + cdef AMF_RESULT res if not WIN32: raise ImportError("amf encoder needs porting to this platform") @@ -500,24 +510,36 @@ cdef class Encoder: with device.get_device_context() as dc: log("device: %s", device.get_info()) log("device context: %s", dc.get_info()) - log("surface: %s", self.get_surface_info(self.surface)) + + self.alloc_surface(&host_surface, AMF_MEMORY_HOST) + + for plane_index in range(2): + log("plane %s src data=%#x", ["Y", "UV"][plane_index], pic_in[plane_index]) + host_texture = self.get_native_plane(host_surface, plane_index) + memcpy( host_texture, pic_in[plane_index], strides[plane_index] * (self.height//2)) + + # make it accessible by the GPU: + res = host_surface.pVtbl.Convert(host_surface, AMF_MEMORY_DX11) + self.check(res, "AMF Convert to DX11 memory") + + self.alloc_surface(&gpu_surface, AMF_MEMORY_DX11) + for plane_index in range(2): - # get the D3D11 destination surface pointer for this plane: - plane = self.surface.pVtbl.GetPlaneAt(self.surface, plane_index) - assert plane - log("plane %s=%s", ["Y", "UV"][plane_index], self.get_plane_info(plane)) - # texture is a `ID3D11Texture2D`: - dst_texture = plane.pVtbl.GetNative(plane) - log("texture=%#x, source=%#x", dst_texture, pic_in[plane_index]) - assert dst_texture - # dc.update_2dtexture(dst_texture, self.width, self.height, - # pic_in[plane_index], strides[plane_index]) + log("plane %s", ["Y", "UV"][plane_index]) + host_texture = self.get_native_plane(host_surface, plane_index) + gpu_texture = self.get_native_plane(gpu_surface, plane_index) + dc.copy_resource(gpu_texture, host_texture) + log("flush()") dc.flush() + log("freeing host surface=%s", host_surface) + host_surface.pVtbl.Release(host_surface) ns = round(1000 * 1000 * monotonic()) - self.set_surface_property(START_TIME_PROPERTY, AMF_VARIANT_INT64, ns) + self.set_surface_property(gpu_surface, START_TIME_PROPERTY, AMF_VARIANT_INT64, ns) - cdef AMF_RESULT res = self.encoder.pVtbl.SubmitInput(self.encoder, self.surface) + log("encoder.SubmitInput()") + res = self.encoder.pVtbl.SubmitInput(self.encoder, gpu_surface) + gpu_surface.pVtbl.Release(gpu_surface) if res == AMF_INPUT_FULL: raise RuntimeError("AMF encoder input is full!") self.check(res, "AMF submitting input to the encoder") @@ -542,7 +564,7 @@ cdef class Encoder: cdef size_t size = 0 try: res = data.pVtbl.QueryInterface(data, &guid, &buffer) - log(f"QueryInterface()={res}") + log(f"QueryInterface()={res} AMFBuffer=%#x", buffer) self.check(res, "AMF data query interface") assert buffer != NULL output = buffer.pVtbl.GetNative(buffer) diff --git a/xpra/platform/win32/d3d11/device.pyx b/xpra/platform/win32/d3d11/device.pyx index ccbf5211fc..c07be794a3 100644 --- a/xpra/platform/win32/d3d11/device.pyx +++ b/xpra/platform/win32/d3d11/device.pyx @@ -161,6 +161,144 @@ cdef extern from "dxgi.h": cdef extern from "d3d11.h": + ctypedef enum DXGI_FORMAT: + DXGI_FORMAT_UNKNOWN + DXGI_FORMAT_R32G32B32A32_TYPELESS + DXGI_FORMAT_R32G32B32A32_FLOAT + DXGI_FORMAT_R32G32B32A32_UINT + DXGI_FORMAT_R32G32B32A32_SINT + DXGI_FORMAT_R32G32B32_TYPELESS + DXGI_FORMAT_R32G32B32_FLOAT + DXGI_FORMAT_R32G32B32_UINT + DXGI_FORMAT_R32G32B32_SINT + DXGI_FORMAT_R16G16B16A16_TYPELESS + DXGI_FORMAT_R16G16B16A16_FLOAT + DXGI_FORMAT_R16G16B16A16_UNORM + DXGI_FORMAT_R16G16B16A16_UINT + DXGI_FORMAT_R16G16B16A16_SNORM + DXGI_FORMAT_R16G16B16A16_SINT + DXGI_FORMAT_R32G32_TYPELESS + DXGI_FORMAT_R32G32_FLOAT + DXGI_FORMAT_R32G32_UINT + DXGI_FORMAT_R32G32_SINT + DXGI_FORMAT_R32G8X24_TYPELESS + DXGI_FORMAT_D32_FLOAT_S8X24_UINT + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT + DXGI_FORMAT_R10G10B10A2_TYPELESS + DXGI_FORMAT_R10G10B10A2_UNORM + DXGI_FORMAT_R10G10B10A2_UINT + DXGI_FORMAT_R11G11B10_FLOAT + DXGI_FORMAT_R8G8B8A8_TYPELESS + DXGI_FORMAT_R8G8B8A8_UNORM + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + DXGI_FORMAT_R8G8B8A8_UINT + DXGI_FORMAT_R8G8B8A8_SNORM + DXGI_FORMAT_R8G8B8A8_SINT + DXGI_FORMAT_R16G16_TYPELESS + DXGI_FORMAT_R16G16_FLOAT + DXGI_FORMAT_R16G16_UNORM + DXGI_FORMAT_R16G16_UINT + DXGI_FORMAT_R16G16_SNORM + DXGI_FORMAT_R16G16_SINT + DXGI_FORMAT_R32_TYPELESS + DXGI_FORMAT_D32_FLOAT + DXGI_FORMAT_R32_FLOAT + DXGI_FORMAT_R32_UINT + DXGI_FORMAT_R32_SINT + DXGI_FORMAT_R24G8_TYPELESS + DXGI_FORMAT_D24_UNORM_S8_UINT + DXGI_FORMAT_R24_UNORM_X8_TYPELESS + DXGI_FORMAT_X24_TYPELESS_G8_UINT + DXGI_FORMAT_R8G8_TYPELESS + DXGI_FORMAT_R8G8_UNORM + DXGI_FORMAT_R8G8_UINT + DXGI_FORMAT_R8G8_SNORM + DXGI_FORMAT_R8G8_SINT + DXGI_FORMAT_R16_TYPELESS + DXGI_FORMAT_R16_FLOAT + DXGI_FORMAT_D16_UNORM + DXGI_FORMAT_R16_UNORM + DXGI_FORMAT_R16_UINT + DXGI_FORMAT_R16_SNORM + DXGI_FORMAT_R16_SINT + DXGI_FORMAT_R8_TYPELESS + DXGI_FORMAT_R8_UNORM + DXGI_FORMAT_R8_UINT + DXGI_FORMAT_R8_SNORM + DXGI_FORMAT_R8_SINT + DXGI_FORMAT_A8_UNORM + DXGI_FORMAT_R1_UNORM + DXGI_FORMAT_R9G9B9E5_SHAREDEXP + DXGI_FORMAT_R8G8_B8G8_UNORM + DXGI_FORMAT_G8R8_G8B8_UNORM + DXGI_FORMAT_BC1_TYPELESS + DXGI_FORMAT_BC1_UNORM + DXGI_FORMAT_BC1_UNORM_SRGB + DXGI_FORMAT_BC2_TYPELESS + DXGI_FORMAT_BC2_UNORM + DXGI_FORMAT_BC2_UNORM_SRGB + DXGI_FORMAT_BC3_TYPELESS + DXGI_FORMAT_BC3_UNORM + DXGI_FORMAT_BC3_UNORM_SRGB + DXGI_FORMAT_BC4_TYPELESS + DXGI_FORMAT_BC4_UNORM + DXGI_FORMAT_BC4_SNORM + DXGI_FORMAT_BC5_TYPELESS + DXGI_FORMAT_BC5_UNORM + DXGI_FORMAT_BC5_SNORM + DXGI_FORMAT_B5G6R5_UNORM + DXGI_FORMAT_B5G5R5A1_UNORM + DXGI_FORMAT_B8G8R8A8_UNORM + DXGI_FORMAT_B8G8R8X8_UNORM + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM + DXGI_FORMAT_B8G8R8A8_TYPELESS + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB + DXGI_FORMAT_B8G8R8X8_TYPELESS + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB + DXGI_FORMAT_BC6H_TYPELESS + DXGI_FORMAT_BC6H_UF16 + DXGI_FORMAT_BC6H_SF16 + DXGI_FORMAT_BC7_TYPELESS + DXGI_FORMAT_BC7_UNORM + DXGI_FORMAT_BC7_UNORM_SRGB + DXGI_FORMAT_AYUV + DXGI_FORMAT_Y410 + DXGI_FORMAT_Y416 + DXGI_FORMAT_NV12 + DXGI_FORMAT_P010 + DXGI_FORMAT_P016 + DXGI_FORMAT_420_OPAQUE + DXGI_FORMAT_YUY2 + DXGI_FORMAT_Y210 + DXGI_FORMAT_Y216 + DXGI_FORMAT_NV11 + DXGI_FORMAT_AI44 + DXGI_FORMAT_IA44 + DXGI_FORMAT_P8 + DXGI_FORMAT_A8P8 + DXGI_FORMAT_B4G4R4A4_UNORM + DXGI_FORMAT_P208 + DXGI_FORMAT_V208 + DXGI_FORMAT_V408 + DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE + DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE + DXGI_FORMAT_FORCE_UINT = 0xffffffff + + ctypedef struct DXGI_SAMPLE_DESC: + UINT Count + UINT Quality + + ctypedef enum D3D11_USAGE: + D3D11_USAGE_DEFAULT + D3D11_USAGE_IMMUTABLE + D3D11_USAGE_DYNAMIC + D3D11_USAGE_STAGING + + ctypedef enum D3D11_CPU_ACCESS_FLAG: + D3D11_CPU_ACCESS_WRITE + D3D11_CPU_ACCESS_READ + ctypedef enum D3D11_DEVICE_CONTEXT_TYPE: D3D11_DEVICE_CONTEXT_IMMEDIATE D3D11_DEVICE_CONTEXT_DEFERRED @@ -260,6 +398,18 @@ cdef extern from "d3d11.h": UINT bottom UINT back + ctypedef struct D3D11_TEXTURE2D_DESC: + UINT Width + UINT Height + UINT MipLevels + UINT ArraySize + DXGI_FORMAT Format + DXGI_SAMPLE_DESC SampleDesc + D3D11_USAGE Usage + UINT BindFlags + UINT CPUAccessFlags + UINT MiscFlags + ctypedef ULONG (*DC_ADDREF)(ID3D11DeviceContext *context) ctypedef ULONG (*DC_RELEASE)(ID3D11DeviceContext *context) ctypedef void (*DC_BEGIN)(ID3D11DeviceContext *context) @@ -435,30 +585,14 @@ cdef class D3D11DeviceContext: assert self.context self.context.lpVtbl.Flush(self.context) - def copy_resource(self, dst: int, src: int) -> None: + def copy_resource(self, uintptr_t dst, uintptr_t src) -> None: + log("D3D11DeviceContext.copy_resource(%#x, %#x)", dst, src) assert self.context assert dst and src cdef ID3D11Resource *r_dst = dst cdef ID3D11Resource *r_src = src self.context.lpVtbl.CopyResource(self.context, r_dst, r_src) - def update_2dtexture(self, dst: int, width: int, height: int, src: int, stride: int) -> None: - log("d3d11.update_resource") - assert self.context - assert dst - cdef ID3D11Resource *r_dst = dst - cdef D3D11_RESOURCE_DIMENSION dim - r_dst.lpVtbl.GetType(r_dst, &dim) - log("d3d11.update_resource dimension(%#x)=%i", dst, dim) - cdef void *data = src - cdef D3D11_BOX box - box.left = box.top = box.front = box.back = 0 - box.right = width - box.bottom = height - cdef int dst_sub = 0 - log("dst=%#x, src=%#x, stride=%i", r_dst, data, stride) - self.context.lpVtbl.UpdateSubresource(self.context, r_dst, dst_sub, &box, data, stride, 0) - def get_info(self) -> Dict[str, Any]: assert self.context flags = self.context.lpVtbl.GetContextFlags(self.context)