游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4383|回复: 6

求助:D3D全屏模式和桌面相互切换的问题

[复制链接]

7

主题

87

帖子

109

积分

注册会员

Rank: 2

积分
109
QQ
发表于 2006-11-19 21:09:00 | 显示全部楼层 |阅读模式
  从D3D全屏模式切换到桌面时,设备对象会丢失。 但重要的问题是:怎样在从桌面切换回D3D全屏模式时恢复设备并继续Present?
  SDK里的D3DFramework还有网上下载的例子都切换的很完美,但是我对它们研究了很长时间,并和我的程序比较,还是没发现什么”机关“。恢复设备的关键操作是什么?有谁知道处理方法?
  谢谢高手指导!我的邮箱:Lv_Ximing@yahoo.com.cn。

5

主题

686

帖子

697

积分

高级会员

Rank: 4

积分
697
QQ
发表于 2006-11-21 09:32:00 | 显示全部楼层

Re:求助:D3D全屏模式和桌面相互切换的问题

用Reset函数……

9

主题

688

帖子

688

积分

高级会员

Rank: 4

积分
688
发表于 2006-11-21 11:47:00 | 显示全部楼层

Re:求助:D3D全屏模式和桌面相互切换的问题

这个问题也困扰了我很久,jk20012001可以讲解得详细些吗?

35

主题

370

帖子

376

积分

中级会员

Rank: 3Rank: 3

积分
376
发表于 2006-11-21 13:39:00 | 显示全部楼层

Re:求助:D3D全屏模式和桌面相互切换的问题

D3DSDK里,设备改变事件触发后会调用这个函数 InitDeviceObjects()

5

主题

686

帖子

697

积分

高级会员

Rank: 4

积分
697
QQ
发表于 2006-11-22 10:33:00 | 显示全部楼层

Re:求助:D3D全屏模式和桌面相互切换的问题

先用TestCooperateLevel来检测当前设备是否丢失,或者在BegeinScene的时候也可以根据函数返回值来检测,如果丢失就释放所有创建在显存的资源(Shader、字体、贴图和模型等),这一步叫InvalidateDeviceObject,然后调用Reset来重置设备状态,最后再恢复释放掉的资源,这一步叫RestoreDeviceObject

7

主题

87

帖子

109

积分

注册会员

Rank: 2

积分
109
QQ
 楼主| 发表于 2006-11-29 21:06:00 | 显示全部楼层

Re:求助:D3D全屏模式和桌面相互切换的问题

谢谢高手指点。
经过多次研究和实验,这个问题我已经搞定。下面是我的一个比较好的解决方法(比D3DFramework的方法好),在此公开一下:

Namespace TouringSon.GameFramework
. . . . . .
    Module Console
  . . . . . .
  Friend Graphics_Device As Direct3D.Device
  Friend Graphics_DeviceEnable As Boolean
  Friend Graphics_DeviceState As Direct3D.PresentParameters
  . . . . . .

  ''' <summary>
  ''' 测试图形设备是否可用。
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Function mGraphics_IsDeviceEnable() As Boolean
    If Graphics_Device Is Nothing Then Graphics_DeviceEnable=False:Return False
    Try
      Graphics_Device.TestCooperativeLevel()
    Catch ex As Direct3D.DeviceLostException '设备刚刚丢失,无法进行任何操作:不可用。
      Graphics_DeviceEnable=False
      Return False
    Catch ex As Direct3D.DeviceNotResetException '设备处于丢失状态丢失,但已经可以进行恢复处理:尝试一次恢复操作(操作结果未知,视为不可用)。
      Graphics_DeviceEnable=False
      Graphics_Device.Reset(Graphics_DeviceState)
      Return False
    End Try
      Graphics_DeviceEnable=True
      Return True
  End Function

  ''' <summary>
  ''' 更新绘图区内容。
  ''' </summary>
  ''' <remarks></remarks>
  Public Sub mGraphicsUpdateScreen()
    检查数据。
    If Graphics_Device Is Nothing Then Exit Sub
    If Graphics_DeviceEnable = False Then Exit Sub
    '刷新。
    Graphics_Device.Present(Graphics_DeviceState.DeviceWindowHandle)
  End Sub
  
  发现关键问题有两个:
  1第二个"Catch“:Graphics_Device.Reset()以后并不能立刻使用,所以我称为”尝试一次恢复“。是否可用要检查下一次TestCoorperativeLevel()的结果。也就是再调用一次我写的mGraphics_IsDeviceEnable()函数。
  这样,使用mGraphics_IsDeviceEnable()在返回设备是否可用的同时就可以恢复设备。可以不断调用并检查返回值直到返回True。用VB6可以模仿写出类似的代码。
  2刷新时的Present():要使用Present(OverrideWindowHandle As IntPtr)重载方法。传递窗口句柄,这个句柄一般和设备丢失之前的窗口相同,我的方法是在PresentParameters.DeviceWindowHandle中保存一个窗体句柄(VB6是D3DPresent_Parameters.hDeviceWindow)。
  以前经常使用不带参数的Present(),所以设备恢复后不知往哪里画图,出现设备恢复正常,但窗口复原并没有图像的现象。
  
  这里只恢复了设备,图形资源的恢复可利用Device的事件处理,但是很麻烦,我更喜欢把资源声明为D3DPool.Managed。

  这是我摸索的经验,至于为何Reset()以后不能立刻使用还不清楚,希望有深入理解Windows窗体内部原理的高手继续讨论。

15

主题

2093

帖子

2093

积分

金牌会员

Rank: 6Rank: 6

积分
2093
发表于 2007-3-26 21:53:00 | 显示全部楼层

Re: 求助:D3D全屏模式和桌面相互切换的问题

我看到的是这样的:
设备丢失后要到了Present的时候才会发生异常
所以只检查Present方法就可以了
        Try
            mDevice.Present()
        Catch
            DevRE()
        End Try
然后恢复设备
    Private Sub DevRE()
        Dim ret As Integer
        mDevice.CheckCooperativeLevel(ret)

        Select Case ret
            Case ResultCode.DeviceLost
                Exit Select
            Case ResultCode.DeviceNotReset
                Try
                    mDevice.Reset(tParsms)
                Catch ex As DeviceLostException
                    System.Threading.Thread.Sleep(10)
                End Try
        End Select
    End Sub
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-4-13 02:19

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表