DDSURFACEDESC2 结构定义一个需求的平面.下面的例子演示了结构的定义和标志位的设定:

// Create the primary surface with one back buffer. 

ZeroMemory(&ddsd, sizeof(ddsd));

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |

                     DDSCAPS_COMPLEX;

ddsd.dwBackBufferCount = 1;



在这个例子中,dwSize成员是DDSURFACEDESC2结构的大小.这是防止你用到的DirectDraw方法返回无效成员的错误.(dwSize是准备给将来的DDSURFACEDESC2结构的扩展用的)


dwFlags成员决定的DDSURFACEDESC2结构中那些成员将被填充有效的信息.例如在DDEx1中,dwFlags被设为你想要用DDSCAPS结构(DDSD_CAPS)和你想创建一个后台缓冲(back buffer)(DDSD_BACKBUFFERCOUNT)


dwCaps成员在例子中标示一个将要在DDSCAPS结构中使用的标志位.在这种情况下,他指定一个主平面(primary surface DDSCAPS_PRIMARYSURFACE),一个交换页(flipping surface DDSCAPS_FLIP),一个合成表面(complex surface DDSCAPS_COMPLEX).


最后,例子指定了一个后台缓冲.后台缓冲就是实际的绘图操作先在那里完成,然后,再快速的翻动(flip)到主平面(primary surface)上.在DDEx1中,后台缓冲的数目是1.其实,你要你的显存允许,你想建几个就建几个.你想知道更多的关于创建大于1块缓冲的信息,可以去看  "triple buffering".


创建的"平面"占用的存储空间,可以是系统内存也可以是显存.如果应用程序使用的空间超出了显存,DirectDraw就会使用系统内存.(例如你指定多块缓存在一个仅有1MB显存的是配器上).你也可以这样设置DDSCAPS结构的dwCaps成员,设成DDSCAPS_VIDEOMEMEORY或DDCAPS_SYSTEMMEMORY以达到只用显存或只用内存.(如指定用显存,而显存不够,IDirectDraw7::CreateSurface返回一个DDERR_OUTOFVIDEOMEMORY错误)

补充:

DDSURFACEDESC2 ddsd;

ddsd.dwSize = sizeof(DDSURFACEDESC2);

dwFlags:这个域用来告诉DirectDraw,你给的数据是用来填充DDSURFACEDESC2的哪个域的。或者,如果你在一个查询操作中用这个结构,告诉DirectDraw你要获得DDSURFACEDESC2的哪个域的信息。看看表6.5,其列出了这个标志字可取的值。比如,你如果你要在 dwWidth 和 dwHeight 两个域中填入有效数据则应该像下面这样设置dwFlags域:

ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;

这样,DirectDraw便知道去查找 dwWidth 和 dwHeight 域,然后放入有效值。就把单位dwFlags看成是引导数据的指示器吧。

表 6.5. DDSURFACEDESC2的dwFlags域的各种可能的标志

        值                          描述 

DDSD_ALPHABITDEPTH    表明 dwAlphaBitDepth 有效 

DDSD_BACKBUFFERCOUNT   表明 dwBackBufferCount 有效 

DDSD_CAPS     表明 ddsCaps 有效

DDSD_CKDESTBLT    表明 ddckCKDestBlt 有效 

DDSD_CKDESTOVERLAY    表明 ddckCKDestOverlay 有效 

DDSD_CKSRCBLT    表明 ddckCKSrcBlt 有效 

DDSD_CKSRCOVERLAY    表明 ddckCKSrcOverlay 有效 

DDSD_HEIGHT     表明 dwHeight 有效

DDSD_LINEARSIZE    表明 dwLinearSize 有效 

DDSD_LPSURFACE    表明 lpSurface 有效 

DDSD_MIPMAPCOUNT    表明 dwMipMapCount 有效 

DDSD_PITCH     表明 lPitch 有效 

DDSD_PIXELFORMAT    表明 ddpfPixelFormat 有效 

DDSD_REFRESHRATE    表明 dwRefreshRate 有效 

DDSD_TEXTURESTAGE    表明 dwTextureStage 有效

DDSD_WIDTH     表明 dwWidth 有效

dwWidth:表明表面的像素宽度。当你创建一个表面是,这里便是你设定宽度的地方。320,640等等。此外,如果你要查询表面的属性,这个域将返回表面的宽度(如果你这么要求的话)。

dwHeight:表面表面的像素高度。与dwWidth类似,这里是你在创建表面时设定其高度的地方。300,240,480等等。

lPitch:这是个有趣的域。基本上它是你所选择模式的水平内存间距。看图6.8。lPitch,也被称为步幅或内存宽度,是在给定视频模式下每行的的字节数。基于如下原因,这是个非常重要的数据域:当你要求一个640×480×8的显示模式,你知道每行有640个像素,每个像素占8位内存(即1个字节)。所以,每行有640个字节,于是lPitch似乎便该设为640。对吗?不一定哦。

                        图 6.8. 访问一个表面

技巧:lPitch将根据VRAM的不同设计而不同。故而,当你在DirectDraw表面上从一行访问另一行的内存时,你必需使用lPitch来移动到下一行,而不是用宽度乘上每像素的字节数。这一点非常之重要。

大多数新显卡支持我们所谓的“线性内存模式”而且有硬件寻址功能,这些属性已经是现实了,但并不保证每块显卡都实现之。所以,你不能假设一个640×480×8视频模式在内存中每行占640个字节。而这便是lPitch域存在的理由。你必需在你计算内存地址时应用它以保证计算正确,这样你便可以从一行移动到另一行了。比如,要访问640×480×8(256色)视频模式下的任何一个像素,你可以使用下面的代码。假设你已经从DirectDraw得到lPitch值,并且lpSurface已经指向表面内存(我会在下面解释这个参数的)

ddsd.lpSurface[x + y*ddsd.lPitch] = color;

是不是很简单啊?大多数情况下,ddsd.lPitch 设为640以代表640x480x8模式。而对于640×480×16模式,ddsd.lPitch 将设为1280(两字节每像素=640×2)。但是,对于某些显卡,出于显存的布局原因,比如内在缓存的设立或其他什么东西,就使得事情不像上述这样了。所以最正规的方式是:在计算内存时总是使用lPitch,你便总是安全的。

技巧:尽管lPitch值并不总是等于你设置的视频模式的水平值,但使用其来测试水平值可以使你能够调用到其他优化函数。比如,在你完成初始化部分功能的代码中,你可以去获得lPitch值并与你选择的视频模式水平值比较。如果它们相等,则你可以切换到你为优化程序而硬编码每行字节数的函数上。

lpSurface:这个域获得指向你随创建表面的真实内存地址的指针。这些内存可能是VRAM也可能是系统内存,但是你无需为次担心。一旦你获得了指向该内存的指针,你便可以像操作其他内存一样操作它了,比如向它写数据或读数据,等等,这完全取决于你想如何填充像素。呵呵,让这个指针有效多容易啊!但是我们还是要在这里多停留一会。一般,你必需“锁定”表面内存,并且告诉DirectX你要在该内存上面工作了而其他的进程不许试图在该内存上读或写。进一步的,当你获得了这个指针时,根据不同的色深(8,16,24,32)你要经常对其进行类型转换并将其复值给一个工作指针。

dwBackBufferCount:这个域被用来设置和读取后备缓存(或与主表面关联的副离屏翻页缓存)的数目。如果你能回忆起来,通过创建一个或更多的虚主表面(与表面拥有同样的图样和色深的缓存),后备缓存可用来实现动画的平滑化,这也便是离屏缓存。然后你在后备缓存上绘图,这个后备缓存对于用户而言是不可见的。接着快速的翻页或拷贝后备缓存到主表面以供显示。如果你只有一个后备缓存,这个技术便成为“双缓存技术”。使用两个缓存便叫“三缓存技术”,当然后者比前者拥有更好的效果但也占用更多的内存。为了是事情简单点,大多数情况下,你将创建一个包括一个主表面和一个后备缓存的翻页链。

ddckCKDestBlt:这个域被用来控制目标颜色键。当进行块传输操作时,这个域控制写入颜色的方式。更多信息将在后面第七章“高级DirectDraw和位图图形”上介绍。

ddckCKSrcBlt:这个域表明源颜色键。即当你进行bitmapping操作时{?后面好像有这个术语,一时想不起来了,但翻到后面再该过来吧。yew98}你不想被块传递的颜色。这是一个你如何设置你位图透明色的的方法。详见第七章。

ddpfPixelFormat:这个域用来获得表明像素的格式。当你去查询表明的属性是这就非常重要了。下面的是其结构。你可能要去查询DirectX SDK以获得更多的细节信息。因为这些信息实在太多了,而且和现在的讨论关心也不大。

typedef struct _DDPIXELFORMAT

        {

        DWORD dwSize;

       DWORD dwFlags;

        DWORD dwFourCC;

        union

        {

        DWORD dwRGBBitCount;

        DWORD dwYUVBitCount;

        DWORD dwZBufferBitDepth;

        DWORD dwAlphaBitDepth;

        DWORD dwLuminanceBitCount; // new for DirectX 6.0

        DWORD dwBumpBitCount;      // new for DirectX 6.0

        } DUMMYUNIONNAMEN(1);

        union

        {

        DWORD dwRBitMask;

        DWORD dwYBitMask;

        DWORD dwStencilBitDepth;   // new for DirectX 6.0

        DWORD dwLuminanceBitMask;  // new for DirectX 6.0

        DWORD dwBumpDuBitMask;     // new for DirectX 6.0

        } DUMMYUNIONNAMEN(2);

        union

        {

        DWORD dwGBitMask;

        DWORD dwUBitMask;

        DWORD dwZBitMask;          // new for DirectX 6.0

        DWORD dwBumpDvBitMask;     // new for DirectX 6.0

        } DUMMYUNIONNAMEN(3);

        union

        {

        DWORD dwBBitMask;

        DWORD dwVBitMask;

        DWORD dwStencilBitMask;    // new for DirectX 6.0

        DWORD dwBumpLuminanceBitMask;  // new for DirectX 6.0

        } DUMMYUNIONNAMEN(4);

        union

        {

        DWORD dwRGBAlphaBitMask;

        DWORD dwYUVAlphaBitMask;

        DWORD dwLuminanceAlphaBitMask; // new for DirectX 6.0

        DWORD dwRGBZBitMask;

        DWORD dwYUVZBitMask;

        } DUMMYUNIONNAMEN(5);

        } DDPIXELFORMAT, FAR* LPDDPIXELFORMAT;

注意:我加粗的域是常用域

ddsCaps:这个域用来使那些被要求的但尚未在表面属性中定义的项有效。事实上,这个域又是另一个数据结构。下面显示了DDSCAPS2:

typedef struct _DDSCAPS2

        {

        DWORD    dwCaps;   // Surface capabilities

        DWORD    dwCaps2;  // More surface capabilities

        DWORD    dwCaps3;  // future expansion

        DWORD    dwCaps4;  // future expansion

        } DDSCAPS2, FAR* LPDDSCAPS2;

在99.9%的情况下,你只需设置该结构的第一个域。dwCaps.dwCaps2 是为3D准备的,而其他域dwCaps3 和 dwCaps4是为未来扩展之用,尚未使用。总之,表6.6列出了dwCaps可能设置的标志值。要看完整的列表,到DirectX SDK里去。

比如当要创建一个主表面是,你可以像下面这样设置ddsd.ddsCaps

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

我知道上面这种表达方式很复杂,在某种程度上确实如此。双重嵌套的控制标志确实有点痛苦。但是,忍受吧……

表 6.6. DirectDraw表面的属性控制设置

        值                                         描述

DDSCAPS_BACKBUFFER     表明这个表面是表面翻页结构中的后备缓存。 

DDSCAPS_COMPLEX     表明是一个复习表面。一个复杂表面是一个与一或多个串成翻页链的后备缓存关联的主表面。 

DDSCAPS_FLIP     表明这个表面是一个表面翻页结构中的一部分。但这个属性被传递给 CreateSurface() 方法时, 一个前端缓存和一个或多个后备     缓存将被创建。 


DDSCAPS_LOCALVIDMEM    表明这个表面优先存在于显存中。如果这个标志选中则 DDSCAPS_VIDEOMEMORY 也必需选中。 

DDSCAPS_MODEX     表明这个表面是一个320x200 或 320x240 的Mode X 表面。 

DDSCAPS_NONLOCALVIDMEM    表明这个表面优先存在于非本地显存中。如果这个标志选中则 DDSCAPS_VIDEOMEMORY 也必需选中。

DDSCAPS_OFFSCREENPLAIN    表明这个表面是个离屏表面。这样该表面便不能是某种特殊表面了,比如不是一个覆盖层,素材,z序,前端缓存,后备缓存,或者     alpha 表面。(Usually used for sprites。) 


DDSCAPS_OWNDC     表明这个表面将长期与一个设备上下文关联。 

DDSCAPS_PRIMARYSURFACE    表明这个表面是主表面。其描述了此刻为用户所见的东西。

DDSCAPS_STANDARDVGAMODE    表明该表面是一个标准的VGA模式的表面,而非 Mode X 模式。这个标志不能与 DDSCAPS_MODEX 标志同时使用。 


DDSCAPS_SYSTEMMEMORY    表明这个表面创建在系统内存中。 

DDSCAPS_VIDEOMEMORY    表明这个表面创建在显存中。

DirectDraw用到的DDSURFACEDESC2的更多相关文章

  1. 初次接触:DirectDraw

    第六章 初次接触:DirectDraw 本章,你将初次接触DirectX中最重要的组件:DirectDraw.DirectDraw可能是DirectX中最强大的技术,因为其贯穿着2D图形绘制同时其帧缓 ...

  2. 调用DirectDraw接口和调DirectDraw7接口的不同点对比

    调用DirectDraw接口步骤: 1.       包含链接库ddraw.lib 2.       初始化窗口类型(全屏独占时类型用popup). 3.       在初始化窗口后初始化Direct ...

  3. DirectDraw

    一.DirectDraw接口 DirectDraw接口图如下: 1.IUnknown:所有COM对象都必须从这个基本接口派生 2.IDirectDraw:这是开始使用DirectDraw时必须创建的主 ...

  4. 用DirectDraw封装的位图动画类

    头文件 [cpp] view plaincopyprint? #pragma once #include <vector> using namespace std; #include &l ...

  5. 使用DirectDraw直接显示YUV视频数据

    最近在编写一个进行视频播放的ActiveX控件,工作已经接近尾声,现将其中显示YUV数据的使用DirectDraw的一些经验总结如下:(解码部分不是我编写的,我负责从网络接收数据,将数据传给解码器,并 ...

  6. 高级DirectDraw

    使用高彩模式 上一章中说了可以用16位的色彩深度,但是16位的色彩深度的数据表示模式可以有两种:Alpha.5.5.5(or X.5.5.5) 和 5.6.5(这是16位色彩最常用的).对于使用哪种1 ...

  7. 第16月第6天 vs2005 lseek directdraw

    1. //_lseek(file_handle, -(int)pbitmap->bitmapinfoheader.biSizeImage, SEEK_END); SetFilePointer(( ...

  8. DirectX - dds图片格式(DDSURFACEDESC2)

    DDS是DirectDraw Surface的缩写,它是DirectX纹理压缩(DirectX Texture Compression,简称DXTC)的产物. DXTC减少了纹理内存消耗的50%甚至更 ...

  9. DirectDraw打造极速图形引擎(Alpha混合)

    显然DirectDraw是Windows下写2D图形程序的最好选择,虽然Direct3D也可以写,但是没DirectDraw简单方便,特别对于初学者,一来就接触那么多函数和参数总不是件愉快的事,所以我 ...

随机推荐

  1. 在Web.config中配置handler

    在Web.config中配置handler节点时发现用vs2010和用vs2015竟然不一样,经过多次测试发现了一些倪端: <configuration> <!--vs2010中需要 ...

  2. lvs+keepalive构建高可用集群

    大纲 一.前言 二.Keepalived 详解 三.环境准备 四.LVS+Keepalived 实现高可用的前端负载均衡器 一.前言        Keepalived使用的vrrp协议方式,虚拟路由 ...

  3. hdu3507 Print Article

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) P ...

  4. sizeof和strlen的使用

    sizeof和strlen的使用 1. sizeof 其值在编译时就计算好了,所以不能用来返回动态分配的内存空姐的大小. 当参数为下面内容是,所表达的含义: 数组——编译时分配的数组空间大小: 指针— ...

  5. 单元测试系列:Mock工具之Mockito实战

    更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6780719.html 在实际项目中写单 ...

  6. inotify-tools使用方法详解

    inotify-tools 是为linux下inotify文件监控工具提供的一套c的开发接口库函数,同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件. inotify-tools是用 ...

  7. Java中常见的排序方法

    本博主要介绍Java中几种常见的排序算法: /* 排序方法的演示1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基 ...

  8. Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器

    本文承接前文Spring源码情操陶冶-自定义节点的解析,分析spring中的context:annotation-config节点如何被解析 源码概览 对BeanDefinitionParser接口的 ...

  9. Node.js爬取豆瓣数据

    一直自以为自己vue还可以,一直自以为webpack还可以,今天在慕课逛node的时候,才发现,自己还差的很远.众所周知,vue-cli基于webpack,而webpack基于node,对node不了 ...

  10. PHP输出打印方法

    PHP这门语言灵活而充满众多的API和用法,然而在这个技术领域里却缺乏一些系统的总结归纳.或许这与PHP语言的诞生方式有关,衍生,快速变化,原始限制等等,诸多因素决定这门语言变得smarty,却没有人 ...