@@ -4555,17 +4555,28 @@ HRESULT m_IDirectDrawSurfaceX::CreateD9Surface()
45554555 HRESULT hr = DD_OK;
45564556
45574557 do {
4558- // Create depth stencil
4558+ // Create depth stencil surface
45594559 if (IsDepthStencil () && surface.Pool != D3DPOOL_SYSTEMMEM)
45604560 {
45614561 surface.IsLockable = false ;
45624562 surface.Type = D3DTYPE_DEPTHSTENCIL;
45634563 surface.Usage = D3DUSAGE_DEPTHSTENCIL;
45644564 surface.Pool = D3DPOOL_DEFAULT;
4565+
4566+ // Get multisample type and quality
45654567 ddrawParent->GetMultiSampleTypeQuality (surface.MultiSampleType , surface.MultiSampleQuality );
4568+
45664569 BOOL Discard = surface.MultiSampleType != D3DMULTISAMPLE_NONE;
4567- if (FAILED ((*d3d9Device)->CreateDepthStencilSurface (surface.Width , surface.Height , Format, surface.MultiSampleType , surface.MultiSampleQuality , Discard, &surface.Surface , nullptr )) &&
4568- FAILED ((*d3d9Device)->CreateDepthStencilSurface (surface.Width , surface.Height , GetFailoverFormat (Format), surface.MultiSampleType , surface.MultiSampleQuality , Discard, &surface.Surface , nullptr )))
4570+
4571+ HRESULT hr_ds = (*d3d9Device)->CreateDepthStencilSurface (surface.Width , surface.Height , Format, surface.MultiSampleType , surface.MultiSampleQuality , Discard, &surface.Surface , nullptr );
4572+
4573+ // Failover format if needed
4574+ if (FAILED (hr_ds))
4575+ {
4576+ hr_ds = (*d3d9Device)->CreateDepthStencilSurface (surface.Width , surface.Height , GetFailoverFormat (Format), surface.MultiSampleType , surface.MultiSampleQuality , Discard, &surface.Surface , nullptr );
4577+ }
4578+
4579+ if (FAILED (hr_ds))
45694580 {
45704581 LOG_LIMIT (100 , __FUNCTION__ << " Error: failed to create depth stencil surface. Size: " << surface.Width << " x" << surface.Height << " Format: " << Format << " dwCaps: " << surfaceDesc2.ddsCaps );
45714582 hr = DDERR_GENERIC;
@@ -4582,8 +4593,16 @@ HRESULT m_IDirectDrawSurfaceX::CreateD9Surface()
45824593 {
45834594 surface.IsLockable = false ;
45844595 surface.Type = D3DTYPE_TEXTURE;
4585- if (FAILED ((*d3d9Device)->CreateTexture (surface.Width , surface.Height , 1 , surface.Usage , Format, surface.Pool , &surface.Texture , nullptr )) &&
4586- FAILED ((*d3d9Device)->CreateTexture (surface.Width , surface.Height , 1 , surface.Usage , GetFailoverFormat (Format), surface.Pool , &surface.Texture , nullptr )))
4596+
4597+ HRESULT hr_tex = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , 1 , surface.Usage , Format, surface.Pool , &surface.Texture , nullptr );
4598+
4599+ // Failover format if needed
4600+ if (FAILED (hr_tex))
4601+ {
4602+ hr_tex = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , 1 , surface.Usage , GetFailoverFormat (Format), surface.Pool , &surface.Texture , nullptr );
4603+ }
4604+
4605+ if (FAILED (hr_tex))
45874606 {
45884607 LOG_LIMIT (100 , __FUNCTION__ << " Error: failed to create render target texture. Size: " << surface.Width << " x" << surface.Height << " Format: " << Format << " dwCaps: " << surfaceDesc2.ddsCaps );
45894608 hr = DDERR_GENERIC;
@@ -4593,10 +4612,22 @@ HRESULT m_IDirectDrawSurfaceX::CreateD9Surface()
45934612 else
45944613 {
45954614 surface.Type = D3DTYPE_RENDERTARGET;
4615+
4616+ // Get multisample info
45964617 ddrawParent->GetMultiSampleTypeQuality (surface.MultiSampleType , surface.MultiSampleQuality );
4618+
4619+ // Determine if lockable
45974620 BOOL IsLockable = !surface.MultiSampleType && !Config.DdrawUseShadowSurface && !(surfaceDesc2.ddsCaps .dwCaps2 & DDSCAPS2_NOTUSERLOCKABLE);
4598- if (FAILED ((*d3d9Device)->CreateRenderTarget (surface.Width , surface.Height , Format, surface.MultiSampleType , surface.MultiSampleQuality , IsLockable, &surface.Surface , nullptr )) &&
4599- FAILED ((*d3d9Device)->CreateRenderTarget (surface.Width , surface.Height , GetFailoverFormat (Format), surface.MultiSampleType , surface.MultiSampleQuality , IsLockable, &surface.Surface , nullptr )))
4621+
4622+ HRESULT hr_rt = (*d3d9Device)->CreateRenderTarget (surface.Width , surface.Height , Format, surface.MultiSampleType , surface.MultiSampleQuality , IsLockable, &surface.Surface , nullptr );
4623+
4624+ // Failover format if needed
4625+ if (FAILED (hr_rt))
4626+ {
4627+ hr_rt = (*d3d9Device)->CreateRenderTarget (surface.Width , surface.Height , GetFailoverFormat (Format), surface.MultiSampleType , surface.MultiSampleQuality , IsLockable, &surface.Surface , nullptr );
4628+ }
4629+
4630+ if (FAILED (hr_rt))
46004631 {
46014632 LOG_LIMIT (100 , __FUNCTION__ << " Error: failed to create render target surface. Size: " << surface.Width << " x" << surface.Height << " Format: " << Format << " dwCaps: " << surfaceDesc2.ddsCaps );
46024633 hr = DDERR_GENERIC;
@@ -4614,58 +4645,77 @@ HRESULT m_IDirectDrawSurfaceX::CreateD9Surface()
46144645 else if (IsTexture)
46154646 {
46164647 surface.Type = D3DTYPE_TEXTURE;
4617- DWORD MipMapLevel = IsMipMapEnabled && !CreateSurfaceEmulated ? surfaceDesc2.dwMipMapCount : 1 ;
4618- HRESULT hr_t ;
4619- do {
4620- surface.Usage = (Config.DdrawForceMipMapAutoGen && MipMapLevel != 1 && (surface.Pool == D3DPOOL_DEFAULT || surface.Pool == D3DPOOL_MANAGED)) ? D3DUSAGE_AUTOGENMIPMAP : 0 ;
4621- DWORD Level = (surface.Usage & D3DUSAGE_AUTOGENMIPMAP) == 0 ? MipMapLevel : 0 ;
4622- // Create texture
4623- hr_t = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , Level, surface.Usage , Format, surface.Pool , &surface.Texture , nullptr );
4624- if (FAILED (hr_t ))
4625- {
4626- hr_t = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , Level, surface.Usage , GetFailoverFormat (Format), surface.Pool , &surface.Texture , nullptr );
4627- }
4628- } while (FAILED (hr_t ) && ((!MipMapLevel && ++MipMapLevel) || --MipMapLevel > 0 ));
4648+
4649+ // Determine mip levels
4650+ DWORD MipMapLevel = (IsMipMapEnabled && !CreateSurfaceEmulated) ? surfaceDesc2.dwMipMapCount : 1 ;
4651+
4652+ // Determine usage
4653+ surface.Usage = 0 ;
4654+ if (Config.DdrawForceMipMapAutoGen && MipMapLevel > 1 && (surface.Pool == D3DPOOL_DEFAULT || surface.Pool == D3DPOOL_MANAGED))
4655+ {
4656+ surface.Usage = D3DUSAGE_AUTOGENMIPMAP;
4657+ }
4658+
4659+ // Adjust levels for autogen mip
4660+ DWORD Levels = (surface.Usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : MipMapLevel;
4661+
4662+ HRESULT hr_t = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , Levels, surface.Usage , Format, surface.Pool , &surface.Texture , nullptr );
4663+
4664+ // Failover format if needed
4665+ if (FAILED (hr_t ))
4666+ {
4667+ hr_t = (*d3d9Device)->CreateTexture (surface.Width , surface.Height , Levels, surface.Usage , GetFailoverFormat (Format), surface.Pool , &surface.Texture , nullptr );
4668+ }
4669+
46294670 if (FAILED (hr_t ))
46304671 {
46314672 LOG_LIMIT (100 , __FUNCTION__ << " Error: failed to create surface texture. Size: " << surface.Width << " x" << surface.Height << " Format: " << Format << " dwCaps: " << surfaceDesc2.ddsCaps );
46324673 hr = DDERR_GENERIC;
46334674 break ;
46344675 }
4676+
4677+ // Set max mip level
46354678 MaxMipMapLevel = (!IsMipMapEnabled || IsMipMapAutogen () || CreateSurfaceEmulated ? 1 : MipMapLevel > 0 ? MipMapLevel : surface.Texture ->GetLevelCount ()) - 1 ;
4679+
4680+ // Ensure MipMaps vector has correct size
46364681 while (MipMaps.size () < MaxMipMapLevel)
46374682 {
4638- MIPMAP MipMap;
4639- MipMaps.push_back (MipMap);
4640- }
4641- if ((surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) && !IsMipMapAutogen ())
4642- {
4643- surfaceDesc2.dwMipMapCount = MipMapLevel;
4683+ MipMaps.emplace_back ();
46444684 }
4685+
46454686 // Set current LOD level
46464687 if (LODLevel != 0 )
46474688 {
46484689 surface.Texture ->SetLOD (LODLevel);
46494690 }
4691+
46504692 // Set current priority
46514693 if (Priority != 0 )
46524694 {
46534695 surface.Texture ->SetPriority (Priority);
46544696 }
46554697 }
4698+ // Create offscreen plain surface
46564699 else
46574700 {
46584701 const D3DFORMAT NewFormat = IsDepthStencil () ? GetStencilEmulatedFormat (surface.BitCount ) : Format;
46594702 surface.Type = D3DTYPE_OFFPLAINSURFACE;
4660- if (FAILED ((*d3d9Device)->CreateOffscreenPlainSurface (surface.Width , surface.Height , NewFormat, surface.Pool , &surface.Surface , nullptr )) &&
4661- FAILED ((*d3d9Device)->CreateOffscreenPlainSurface (surface.Width , surface.Height , GetFailoverFormat (NewFormat), surface.Pool , &surface.Surface , nullptr )))
4703+
4704+ HRESULT hr_off = (*d3d9Device)->CreateOffscreenPlainSurface (surface.Width , surface.Height , NewFormat, surface.Pool , &surface.Surface , nullptr );
4705+
4706+ // Failover format if needed
4707+ if (FAILED (hr_off))
4708+ {
4709+ hr_off = (*d3d9Device)->CreateOffscreenPlainSurface (surface.Width , surface.Height , GetFailoverFormat (NewFormat), surface.Pool , &surface.Surface , nullptr );
4710+ }
4711+
4712+ if (FAILED (hr_off))
46624713 {
46634714 LOG_LIMIT (100 , __FUNCTION__ << " Error: failed to create offplain surface. Size: " << surface.Width << " x" << surface.Height << " Format: " << NewFormat << " dwCaps: " << surfaceDesc2.ddsCaps );
46644715 hr = DDERR_GENERIC;
46654716 break ;
46664717 }
46674718 }
4668-
46694719 if (FAILED (CreateD9AuxiliarySurfaces ()))
46704720 {
46714721 hr = DDERR_GENERIC;
@@ -6363,40 +6413,15 @@ void m_IDirectDrawSurfaceX::InitSurfaceDesc(DWORD DirectXVersion)
63636413 surfaceDesc2.dwBackBufferCount = 0 ;
63646414 }
63656415
6366- // Handle mipmaps
6367- if ((!(surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) || ((surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) && surfaceDesc2.dwMipMapCount != 1 )) &&
6368- (surfaceDesc2.ddsCaps .dwCaps & (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX | DDSCAPS_TEXTURE)) == (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX | DDSCAPS_TEXTURE))
6369- {
6370- // Compute width and height
6371- if ((!(surfaceDesc2.dwFlags & (DDSD_WIDTH | DDSD_HEIGHT)) || (!surfaceDesc2.dwWidth && !surfaceDesc2.dwHeight )) &&
6372- (surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) && surfaceDesc2.dwMipMapCount > 0 )
6373- {
6374- surfaceDesc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
6375- surfaceDesc2.dwWidth = (DWORD)pow (2 , surfaceDesc2.dwMipMapCount - 1 );
6376- surfaceDesc2.dwHeight = surfaceDesc2.dwWidth ;
6377- }
6378- // Compute mipcount
6379- DWORD MipMapLevelCount = ((surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) && surfaceDesc2.dwMipMapCount ) ? surfaceDesc2.dwMipMapCount :
6380- GetMaxMipMapLevel (surfaceDesc2.dwWidth , surfaceDesc2.dwHeight );
6381- MaxMipMapLevel = MipMapLevelCount - 1 ;
6382- surfaceDesc2.dwMipMapCount = MaxMipMapLevel + 1 ;
6383- surfaceDesc2.dwFlags |= DDSD_MIPMAPCOUNT;
6384- }
63856416 // Mipmap textures
6386- else if (surfaceDesc2.ddsCaps .dwCaps & DDSCAPS_MIPMAP)
6417+ if ((surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT) && (surfaceDesc2.dwMipMapCount > 1 ) &&
6418+ ((surfaceDesc2.ddsCaps .dwCaps & (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX | DDSCAPS_TEXTURE)) == (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX | DDSCAPS_TEXTURE)))
63876419 {
6388- if (surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT)
6389- {
6390- surfaceDesc2.dwMipMapCount = 1 ;
6391- }
6420+ MaxMipMapLevel = surfaceDesc2.dwMipMapCount - 1 ;
63926421 }
63936422 // No mipmaps
63946423 else
63956424 {
6396- if (surfaceDesc2.dwFlags & DDSD_MIPMAPCOUNT)
6397- {
6398- surfaceDesc2.dwMipMapCount = 0 ;
6399- }
64006425 surfaceDesc2.dwFlags &= ~DDSD_MIPMAPCOUNT;
64016426 surfaceDesc2.ddsCaps .dwCaps &= ~DDSCAPS_MIPMAP;
64026427 }
0 commit comments