static struct mp_image *alloc_pool(void *pctx, int fmt, int w, int h) { struct vf_instance *vf = pctx; struct vf_priv_s *p = vf->priv; HRESULT hr; ID3D11Texture2D *texture = NULL; D3D11_TEXTURE2D_DESC texdesc = { .Width = w, .Height = h, .Format = p->out_format, .MipLevels = 1, .ArraySize = 1, .SampleDesc = { .Count = 1 }, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, .MiscFlags = p->out_shared ? D3D11_RESOURCE_MISC_SHARED : 0, }; hr = ID3D11Device_CreateTexture2D(p->vo_dev, &texdesc, NULL, &texture); if (FAILED(hr)) return NULL; struct mp_image *mpi = mp_image_new_custom_ref(NULL, texture, release_tex); if (!mpi) abort(); mp_image_setfmt(mpi, p->out_params.imgfmt); mp_image_set_size(mpi, w, h); mpi->params.hw_subfmt = p->out_params.hw_subfmt; mpi->planes[1] = (void *)texture; mpi->planes[2] = (void *)(intptr_t)0; return mpi; }
static inline bool gl_shtex_init_d3d11_tex(void) { IDXGIResource *dxgi_res; HRESULT hr; D3D11_TEXTURE2D_DESC desc = {0}; desc.Width = data.cx; desc.Height = data.cy; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; hr = ID3D11Device_CreateTexture2D(data.d3d11_device, &desc, NULL, &data.d3d11_tex); if (FAILED(hr)) { hlog_hr("gl_shtex_init_d3d11_tex: failed to create texture", hr); return false; } hr = ID3D11Device_QueryInterface(data.d3d11_tex, &GUID_IDXGIResource, (void**)&dxgi_res); if (FAILED(hr)) { hlog_hr("gl_shtex_init_d3d11_tex: failed to get IDXGIResource", hr); return false; } hr = IDXGIResource_GetSharedHandle(dxgi_res, &data.handle); IDXGIResource_Release(dxgi_res); if (FAILED(hr)) { hlog_hr("gl_shtex_init_d3d11_tex: failed to get shared handle", hr); return false; } return true; }
static int d3d11va_init_decoder(struct lavc_ctx *s, int w, int h) { HRESULT hr; int ret = -1; struct priv *p = s->hwdec_priv; TA_FREEP(&p->decoder); ID3D11Texture2D *texture = NULL; void *tmp = talloc_new(NULL); UINT n_guids = ID3D11VideoDevice_GetVideoDecoderProfileCount(p->video_dev); GUID *device_guids = talloc_array(tmp, GUID, n_guids); for (UINT i = 0; i < n_guids; i++) { GUID *guid = &device_guids[i]; hr = ID3D11VideoDevice_GetVideoDecoderProfile(p->video_dev, i, guid); if (FAILED(hr)) { MP_ERR(p, "Failed to get VideoDecoderProfile %d: %s\n", i, mp_HRESULT_to_str(hr)); goto done; } dump_decoder_info(s, guid); } struct d3d_decoder_fmt fmt = d3d_select_decoder_mode(s, device_guids, n_guids, d3d11_formats, MP_ARRAY_SIZE(d3d11_formats), d3d11_format_supported); if (!fmt.format) { MP_ERR(p, "Failed to find a suitable decoder\n"); goto done; } struct d3d11va_decoder *decoder = talloc_zero(tmp, struct d3d11va_decoder); talloc_set_destructor(decoder, d3d11va_destroy_decoder); decoder->mpfmt_decoded = fmt.format->mpfmt; int n_surfaces = hwdec_get_max_refs(s) + ADDITIONAL_SURFACES; int w_align = w, h_align = h; d3d_surface_align(s, &w_align, &h_align); D3D11_TEXTURE2D_DESC tex_desc = { .Width = w_align, .Height = h_align, .MipLevels = 1, .Format = fmt.format->dxfmt, .SampleDesc.Count = 1, .MiscFlags = 0, .ArraySize = n_surfaces, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE, .CPUAccessFlags = 0, }; hr = ID3D11Device_CreateTexture2D(p->device, &tex_desc, NULL, &texture); if (FAILED(hr)) { MP_ERR(p, "Failed to create Direct3D11 texture with %d surfaces: %s\n", n_surfaces, mp_HRESULT_to_str(hr)); goto done; } if (s->hwdec->type == HWDEC_D3D11VA_COPY) { // create staging texture shared with the CPU with mostly the same // parameters as the above decoder-bound texture ID3D11Texture2D_GetDesc(texture, &tex_desc); tex_desc.MipLevels = 1; tex_desc.MiscFlags = 0; tex_desc.ArraySize = 1; tex_desc.Usage = D3D11_USAGE_STAGING; tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; tex_desc.BindFlags = 0; hr = ID3D11Device_CreateTexture2D(p->device, &tex_desc, NULL, &decoder->staging); if (FAILED(hr)) { MP_ERR(p, "Failed to create staging texture: %s\n", mp_HRESULT_to_str(hr)); goto done; } } // pool to hold the mp_image wrapped surfaces decoder->pool = talloc_steal(decoder, mp_image_pool_new(n_surfaces)); // array of the same surfaces (needed by ffmpeg) ID3D11VideoDecoderOutputView **surfaces = talloc_array_ptrtype(decoder->pool, surfaces, n_surfaces); D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = { .DecodeProfile = *fmt.guid, .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D, }; for (int i = 0; i < n_surfaces; i++) { ID3D11VideoDecoderOutputView **surface = &surfaces[i]; view_desc.Texture2D.ArraySlice = i; hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( p->video_dev, (ID3D11Resource *)texture, &view_desc, surface); if (FAILED(hr)) { MP_ERR(p, "Failed getting decoder output view %d: %s\n", i, mp_HRESULT_to_str(hr)); goto done; } struct mp_image *img = d3d11va_new_ref(*surface, w, h); ID3D11VideoDecoderOutputView_Release(*surface); // transferred to img if (!img) { MP_ERR(p, "Failed to create D3D11VA image %d\n", i); goto done; } mp_image_pool_add(decoder->pool, img); // transferred to pool } D3D11_VIDEO_DECODER_DESC decoder_desc = { .Guid = *fmt.guid, .SampleWidth = w, .SampleHeight = h, .OutputFormat = fmt.format->dxfmt, }; UINT n_cfg; hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(p->video_dev, &decoder_desc, &n_cfg); if (FAILED(hr)) { MP_ERR(p, "Failed to get number of decoder configurations: %s)", mp_HRESULT_to_str(hr)); goto done; } // pick the config with the highest score D3D11_VIDEO_DECODER_CONFIG *decoder_config = talloc_zero(decoder, D3D11_VIDEO_DECODER_CONFIG); unsigned max_score = 0; for (UINT i = 0; i < n_cfg; i++) { D3D11_VIDEO_DECODER_CONFIG cfg; hr = ID3D11VideoDevice_GetVideoDecoderConfig(p->video_dev, &decoder_desc, i, &cfg); if (FAILED(hr)) { MP_ERR(p, "Failed to get decoder config %d: %s\n", i, mp_HRESULT_to_str(hr)); goto done; } unsigned score = d3d_decoder_config_score( s, &cfg.guidConfigBitstreamEncryption, cfg.ConfigBitstreamRaw); if (score > max_score) { max_score = score; *decoder_config = cfg; } } if (!max_score) { MP_ERR(p, "Failed to find a suitable decoder configuration\n"); goto done; } hr = ID3D11VideoDevice_CreateVideoDecoder(p->video_dev, &decoder_desc, decoder_config, &decoder->decoder); if (FAILED(hr)) { MP_ERR(p, "Failed to create video decoder: %s\n", mp_HRESULT_to_str(hr)); goto done; } struct AVD3D11VAContext *avd3d11va_ctx = s->avctx->hwaccel_context; avd3d11va_ctx->decoder = decoder->decoder; avd3d11va_ctx->video_context = p->video_ctx; avd3d11va_ctx->cfg = decoder_config; avd3d11va_ctx->surface_count = n_surfaces; avd3d11va_ctx->surface = surfaces; avd3d11va_ctx->workaround = is_clearvideo(fmt.guid) ? FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO : 0; p->decoder = talloc_steal(NULL, decoder); ret = 0; done: // still referenced by pool images / surfaces if (texture) ID3D11Texture2D_Release(texture); talloc_free(tmp); return ret; } static void destroy_device(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (p->device) ID3D11Device_Release(p->device); if (p->device_ctx) ID3D11DeviceContext_Release(p->device_ctx); } static bool create_device(struct lavc_ctx *s, BOOL thread_safe) { HRESULT hr; struct priv *p = s->hwdec_priv; d3d_load_dlls(); if (!d3d11_dll) { MP_ERR(p, "Failed to load D3D11 library\n"); return false; } PFN_D3D11_CREATE_DEVICE CreateDevice = (void *)GetProcAddress(d3d11_dll, "D3D11CreateDevice"); if (!CreateDevice) { MP_ERR(p, "Failed to get D3D11CreateDevice symbol from DLL: %s\n", mp_LastError_to_str()); return false; } hr = CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0, D3D11_SDK_VERSION, &p->device, NULL, &p->device_ctx); if (FAILED(hr)) { MP_ERR(p, "Failed to create D3D11 Device: %s\n", mp_HRESULT_to_str(hr)); return false; } ID3D10Multithread *multithread; hr = ID3D11Device_QueryInterface(p->device, &IID_ID3D10Multithread, (void **)&multithread); if (FAILED(hr)) { MP_ERR(p, "Failed to get Multithread interface: %s\n", mp_HRESULT_to_str(hr)); return false; } ID3D10Multithread_SetMultithreadProtected(multithread, thread_safe); ID3D10Multithread_Release(multithread); return true; } static void d3d11va_uninit(struct lavc_ctx *s) { struct priv *p = s->hwdec_priv; if (!p) return; talloc_free(p->decoder); av_freep(&s->avctx->hwaccel_context); if (p->video_dev) ID3D11VideoDevice_Release(p->video_dev); if (p->video_ctx) ID3D11VideoContext_Release(p->video_ctx); destroy_device(s); TA_FREEP(&s->hwdec_priv); } static int d3d11va_init(struct lavc_ctx *s) { HRESULT hr; struct priv *p = talloc_zero(NULL, struct priv); if (!p) return -1; s->hwdec_priv = p; p->log = mp_log_new(s, s->log, "d3d11va"); if (s->hwdec->type == HWDEC_D3D11VA_COPY) { mp_check_gpu_memcpy(p->log, NULL); p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } p->device = hwdec_devices_load(s->hwdec_devs, s->hwdec->type); if (p->device) { ID3D11Device_AddRef(p->device); ID3D11Device_GetImmediateContext(p->device, &p->device_ctx); if (!p->device_ctx) goto fail; MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device); } else if (s->hwdec->type == HWDEC_D3D11VA) { MP_ERR(p, "No Direct3D device provided for native d3d11 decoding\n"); goto fail; } else { if (!create_device(s, FALSE)) goto fail; } hr = ID3D11DeviceContext_QueryInterface(p->device_ctx, &IID_ID3D11VideoContext, (void **)&p->video_ctx); if (FAILED(hr)) { MP_ERR(p, "Failed to get VideoContext interface: %s\n", mp_HRESULT_to_str(hr)); goto fail; } hr = ID3D11Device_QueryInterface(p->device, &IID_ID3D11VideoDevice, (void **)&p->video_dev); if (FAILED(hr)) { MP_ERR(p, "Failed to get VideoDevice interface. %s\n", mp_HRESULT_to_str(hr)); goto fail; } s->avctx->hwaccel_context = av_d3d11va_alloc_context(); if (!s->avctx->hwaccel_context) { MP_ERR(p, "Failed to allocate hwaccel_context\n"); goto fail; } return 0; fail: d3d11va_uninit(s); return -1; } static int d3d11va_probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { // d3d11va-copy can do without external context; dxva2 requires it. if (hwdec->type != HWDEC_D3D11VA_COPY) { if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_D3D11VA)) return HWDEC_ERR_NO_CTX; } return d3d_probe_codec(codec); } const struct vd_lavc_hwdec mp_vd_lavc_d3d11va = { .type = HWDEC_D3D11VA, .image_format = IMGFMT_D3D11VA, .probe = d3d11va_probe, .init = d3d11va_init, .uninit = d3d11va_uninit, .init_decoder = d3d11va_init_decoder, .allocate_image = d3d11va_allocate_image, .process_image = d3d11va_update_image_attribs, }; const struct vd_lavc_hwdec mp_vd_lavc_d3d11va_copy = { .type = HWDEC_D3D11VA_COPY, .copying = true, .image_format = IMGFMT_D3D11VA, .probe = d3d11va_probe, .init = d3d11va_init, .uninit = d3d11va_uninit, .init_decoder = d3d11va_init_decoder, .allocate_image = d3d11va_allocate_image, .process_image = d3d11va_retrieve_image, .delay_queue = HWDEC_DELAY_QUEUE_COUNT, };
/** * It creates a Direct3D11 decoder using the given video format */ static int DxCreateDecoderSurfaces(vlc_va_t *va, int codec_id, const video_format_t *fmt, bool b_threading) { vlc_va_sys_t *sys = va->sys; directx_sys_t *dx_sys = &va->sys->dx_sys; HRESULT hr; ID3D10Multithread *pMultithread; hr = ID3D11Device_QueryInterface( (ID3D11Device*) dx_sys->d3ddev, &IID_ID3D10Multithread, (void **)&pMultithread); if (SUCCEEDED(hr)) { ID3D10Multithread_SetMultithreadProtected(pMultithread, b_threading && dx_sys->thread_count > 1); ID3D10Multithread_Release(pMultithread); } D3D11_TEXTURE2D_DESC texDesc; ZeroMemory(&texDesc, sizeof(texDesc)); texDesc.Width = dx_sys->surface_width; texDesc.Height = dx_sys->surface_height; texDesc.MipLevels = 1; texDesc.Format = sys->render; texDesc.SampleDesc.Count = 1; texDesc.MiscFlags = 0; texDesc.ArraySize = dx_sys->surface_count; texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.BindFlags = D3D11_BIND_DECODER; texDesc.CPUAccessFlags = 0; ID3D11Texture2D *p_texture; hr = ID3D11Device_CreateTexture2D( (ID3D11Device*) dx_sys->d3ddev, &texDesc, NULL, &p_texture ); if (FAILED(hr)) { msg_Err(va, "CreateTexture2D %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); return VLC_EGENERIC; } D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; ZeroMemory(&viewDesc, sizeof(viewDesc)); viewDesc.DecodeProfile = dx_sys->input; viewDesc.ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D; int surface_count = dx_sys->surface_count; for (dx_sys->surface_count = 0; dx_sys->surface_count < surface_count; dx_sys->surface_count++) { viewDesc.Texture2D.ArraySlice = dx_sys->surface_count; hr = ID3D11VideoDevice_CreateVideoDecoderOutputView( (ID3D11VideoDevice*) dx_sys->d3ddec, (ID3D11Resource*) p_texture, &viewDesc, (ID3D11VideoDecoderOutputView**) &dx_sys->hw_surface[dx_sys->surface_count] ); if (FAILED(hr)) { msg_Err(va, "CreateVideoDecoderOutputView %d failed. (hr=0x%0lx)", dx_sys->surface_count, hr); ID3D11Texture2D_Release(p_texture); return VLC_EGENERIC; } } msg_Dbg(va, "ID3D11VideoDecoderOutputView succeed with %d surfaces (%dx%d)", dx_sys->surface_count, dx_sys->surface_width, dx_sys->surface_height); D3D11_VIDEO_DECODER_DESC decoderDesc; ZeroMemory(&decoderDesc, sizeof(decoderDesc)); decoderDesc.Guid = dx_sys->input; decoderDesc.SampleWidth = fmt->i_width; decoderDesc.SampleHeight = fmt->i_height; decoderDesc.OutputFormat = sys->render; UINT cfg_count; hr = ID3D11VideoDevice_GetVideoDecoderConfigCount( (ID3D11VideoDevice*) dx_sys->d3ddec, &decoderDesc, &cfg_count ); if (FAILED(hr)) { msg_Err(va, "GetVideoDecoderConfigCount failed. (hr=0x%lX)", hr); return VLC_EGENERIC; } /* List all configurations available for the decoder */ D3D11_VIDEO_DECODER_CONFIG cfg_list[cfg_count]; for (unsigned i = 0; i < cfg_count; i++) { hr = ID3D11VideoDevice_GetVideoDecoderConfig( (ID3D11VideoDevice*) dx_sys->d3ddec, &decoderDesc, i, &cfg_list[i] ); if (FAILED(hr)) { msg_Err(va, "GetVideoDecoderConfig failed. (hr=0x%lX)", hr); return VLC_EGENERIC; } } msg_Dbg(va, "we got %d decoder configurations", cfg_count); /* Select the best decoder configuration */ int cfg_score = 0; for (unsigned i = 0; i < cfg_count; i++) { const D3D11_VIDEO_DECODER_CONFIG *cfg = &cfg_list[i]; /* */ msg_Dbg(va, "configuration[%d] ConfigBitstreamRaw %d", i, cfg->ConfigBitstreamRaw); /* */ int score; if (cfg->ConfigBitstreamRaw == 1) score = 1; else if (codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2) score = 2; else continue; if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA_NoEncrypt)) score += 16; if (cfg_score < score) { sys->cfg = *cfg; cfg_score = score; } } if (cfg_score <= 0) { msg_Err(va, "Failed to find a supported decoder configuration"); return VLC_EGENERIC; } /* Create the decoder */ ID3D11VideoDecoder *decoder; hr = ID3D11VideoDevice_CreateVideoDecoder( (ID3D11VideoDevice*) dx_sys->d3ddec, &decoderDesc, &sys->cfg, &decoder ); if (FAILED(hr)) { msg_Err(va, "ID3D11VideoDevice_CreateVideoDecoder failed. (hr=0x%lX)", hr); dx_sys->decoder = NULL; return VLC_EGENERIC; } dx_sys->decoder = (IUnknown*) decoder; msg_Dbg(va, "DxCreateDecoderSurfaces succeed"); return VLC_SUCCESS; }
qboolean D3D11_BeginShadowMap(int id, int w, int h) { D3D11_TEXTURE2D_DESC texdesc; HRESULT hr; if (!shadowmap_dsview[id] && !shadowmap_rtview[id]) { memset(&texdesc, 0, sizeof(texdesc)); texdesc.Width = w; texdesc.Height = h; texdesc.MipLevels = 1; texdesc.ArraySize = 1; texdesc.Format = shadowfmts[shadowfmt][1]; texdesc.SampleDesc.Count = 1; texdesc.SampleDesc.Quality = 0; texdesc.Usage = D3D11_USAGE_DEFAULT; texdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; texdesc.CPUAccessFlags = 0; texdesc.MiscFlags = 0; if (shadowfmt == 2) texdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; // Create the texture if (!shadowmap_texture[id].ptr) { hr = ID3D11Device_CreateTexture2D(pD3DDev11, &texdesc, NULL, (ID3D11Texture2D **)&shadowmap_texture[id].ptr); if (FAILED(hr)) return false; } if (shadowfmt == 2) { hr = ID3D11Device_CreateRenderTargetView(pD3DDev11, (ID3D11Resource *)shadowmap_texture[id].ptr, NULL, &shadowmap_rtview[id]); } else { D3D11_DEPTH_STENCIL_VIEW_DESC rtdesc; rtdesc.Format = shadowfmts[shadowfmt][2]; rtdesc.Flags = 0; rtdesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; rtdesc.Texture2D.MipSlice = 0; hr = ID3D11Device_CreateDepthStencilView(pD3DDev11, (ID3D11Resource *)shadowmap_texture[id].ptr, &rtdesc, &shadowmap_dsview[id]); } if (FAILED(hr)) return false; } D3D11BE_UnbindAllTextures(); if (shadowfmt == 2) { float colours[4] = {0, 1, 0, 0}; colours[0] = frandom(); colours[1] = frandom(); colours[2] = frandom(); ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 1, &shadowmap_rtview[id], shadowmap_dsview[id]); ID3D11DeviceContext_ClearRenderTargetView(d3ddevctx, shadowmap_rtview[id], colours); } else { ID3D11DeviceContext_OMSetRenderTargets(d3ddevctx, 0, NULL, shadowmap_dsview[id]); ID3D11DeviceContext_ClearDepthStencilView(d3ddevctx, shadowmap_dsview[id], D3D11_CLEAR_DEPTH, 1.0f, 0); } return true; }
qboolean D3D11_LoadTextureMips(image_t *tex, struct pendingtextureinfo *mips) { int bytesperpixel = 4; int bcbytes = 0; HRESULT hr; D3D11_TEXTURE2D_DESC tdesc = {0}; D3D11_SUBRESOURCE_DATA subresdesc[sizeof(mips->mip) / sizeof(mips->mip[0])]; int i; if (!sh_config.texfmt[mips->encoding]) { Con_Printf("Texture encoding %i not supported by d3d11\n", mips->encoding); return false; } tdesc.Width = mips->mip[0].width; tdesc.Height = mips->mip[0].height; tdesc.ArraySize = 1; tdesc.SampleDesc.Count = 1; tdesc.SampleDesc.Quality = 0; tdesc.Usage = mips->mip[0].data?D3D11_USAGE_IMMUTABLE:D3D11_USAGE_DYNAMIC; tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; tdesc.CPUAccessFlags = (mips->mip[0].data)?0:D3D11_CPU_ACCESS_WRITE; tdesc.MiscFlags = 0; if (tex->flags & IF_RENDERTARGET) { tdesc.BindFlags |= D3D11_BIND_RENDER_TARGET; tdesc.Usage = D3D11_USAGE_DEFAULT; tdesc.CPUAccessFlags = 0; } if (mips->type == PTI_CUBEMAP) { tdesc.ArraySize *= 6; tdesc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; } else if (mips->type == PTI_3D) return false; //nyi //d3d11.1 formats #define DXGI_FORMAT_B4G4R4A4_UNORM 115 switch(mips->encoding) { default: return false; case PTI_DEPTH16: tdesc.Format = DXGI_FORMAT_D16_UNORM; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; bytesperpixel = 2; break; case PTI_DEPTH24: tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; bytesperpixel = 3; break; case PTI_DEPTH32: tdesc.Format = DXGI_FORMAT_D32_FLOAT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; bytesperpixel = 4; break; case PTI_DEPTH24_8: tdesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; bytesperpixel = 4; break; case PTI_RGB565: tdesc.Format = DXGI_FORMAT_B5G6R5_UNORM; bytesperpixel = 2; break; // case PTI_RGBA5551: // tdesc.Format = DXGI_FORMAT_A1B5G5R5_UNORM; // bytesperpixel = 2; // break; case PTI_ARGB1555: tdesc.Format = DXGI_FORMAT_B5G5R5A1_UNORM; bytesperpixel = 2; break; case PTI_RGBA4444: tdesc.Format = DXGI_FORMAT_B4G4R4A4_UNORM; bytesperpixel = 2; break; // case PTI_ARGB4444: // tdesc.Format = DXGI_FORMAT_A4B4G4R4_UNORM; // bytesperpixel = 2; // break; case PTI_RGBA8: tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; bytesperpixel = 4; break; case PTI_RGBX8: //d3d11 has no alphaless format. be sure to proprly disable alpha in the shader. tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; bytesperpixel = 4; break; case PTI_BGRA8: tdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; bytesperpixel = 4; break; case PTI_BGRX8: tdesc.Format = DXGI_FORMAT_B8G8R8X8_UNORM; bytesperpixel = 4; break; case PTI_S3RGB1: //d3d11 provides no way to disable alpha with dxt1. be sure to proprly disable alpha in the shader. case PTI_S3RGBA1: tdesc.Format = DXGI_FORMAT_BC1_UNORM; bcbytes = 8; break; case PTI_S3RGBA3: tdesc.Format = DXGI_FORMAT_BC2_UNORM; bcbytes = 16; break; case PTI_S3RGBA5: tdesc.Format = DXGI_FORMAT_BC3_UNORM; bcbytes = 16; break; } if (!mips->mip[0].data) { subresdesc[0].pSysMem = NULL; //one mip, but no data. happens with rendertargets tdesc.MipLevels = 1; } else { for (i = 0; i < mips->mipcount; i++) { subresdesc[i].pSysMem = mips->mip[i].data; if (bcbytes) { subresdesc[i].SysMemPitch = ((mips->mip[i].width+3)/4) * bcbytes; subresdesc[i].SysMemSlicePitch = mips->mip[i].datasize; } else { subresdesc[i].SysMemPitch = mips->mip[i].width*bytesperpixel; subresdesc[i].SysMemSlicePitch = mips->mip[i].datasize;//mips->mip[i].width*mips->mip[i].height*bytesperpixel; } } tdesc.MipLevels = i/tdesc.ArraySize; } D3D11_DestroyTexture(tex); hr = ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, (mips->mip[0].data?subresdesc:NULL), (ID3D11Texture2D**)&tex->ptr); return !FAILED(hr); }
sgui_ctx_wm* d3d11_wm_create( sgui_window* wnd ) { D3D11_SHADER_RESOURCE_VIEW_DESC rvdesc; D3D11_SAMPLER_DESC sampdesc; D3D11_SUBRESOURCE_DATA data; unsigned int width, height; D3D11_TEXTURE2D_DESC desc; sgui_d3d11_context* ctx; sgui_subwm_skin* skin; sgui_d3d11_wm* this; sgui_ctx_wm* super; HRESULT status; ctx = (sgui_d3d11_context*)sgui_window_get_context( wnd ); if( !ctx ) return NULL; this = calloc( 1, sizeof(sgui_d3d11_wm) ); super = (sgui_ctx_wm*)this; if( !this ) return NULL; memset( &desc, 0, sizeof(desc) ); memset( &data, 0, sizeof(data) ); memset( &rvdesc, 0, sizeof(rvdesc) ); memset( &sampdesc, 0, sizeof(sampdesc) ); skin = sgui_subwm_skin_get( ); skin->get_ctx_skin_texture_size( skin, &width, &height ); desc.Width = width; desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; desc.SampleDesc.Count = 1; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.Usage = D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; data.pSysMem = skin->get_ctx_skin_texture( skin ); data.SysMemPitch = width*4; rvdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; rvdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; rvdesc.Texture2D.MipLevels = 1; sampdesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; sampdesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampdesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampdesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampdesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; status = ID3D11Device_CreateTexture2D( ctx->dev, &desc, &data, &this->skintex ); if( status!=S_OK || !this->skintex ) goto fail; status = ID3D11Device_CreateShaderResourceView( ctx->dev, (void*)this->skintex, &rvdesc, &this->view ); if( status!=S_OK || !this->view ) goto failtex; status = ID3D11Device_CreateSamplerState( ctx->dev, &sampdesc, &this->sampler ); if( status!=S_OK || !this->sampler ) goto failview; /* init */ super->wnd = wnd; super->draw_gui = d3d11_wm_draw_gui; super->destroy = d3d11_wm_destroy; return super; failview: ID3D11ShaderResourceView_Release( this->view ); failtex: ID3D11Texture2D_Release( this->skintex ); fail: free( this ); return NULL; }