DirectDraw用到的DDSURFACEDESC2
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的更多相关文章
- 初次接触:DirectDraw
第六章 初次接触:DirectDraw 本章,你将初次接触DirectX中最重要的组件:DirectDraw.DirectDraw可能是DirectX中最强大的技术,因为其贯穿着2D图形绘制同时其帧缓 ...
- 调用DirectDraw接口和调DirectDraw7接口的不同点对比
调用DirectDraw接口步骤: 1. 包含链接库ddraw.lib 2. 初始化窗口类型(全屏独占时类型用popup). 3. 在初始化窗口后初始化Direct ...
- DirectDraw
一.DirectDraw接口 DirectDraw接口图如下: 1.IUnknown:所有COM对象都必须从这个基本接口派生 2.IDirectDraw:这是开始使用DirectDraw时必须创建的主 ...
- 用DirectDraw封装的位图动画类
头文件 [cpp] view plaincopyprint? #pragma once #include <vector> using namespace std; #include &l ...
- 使用DirectDraw直接显示YUV视频数据
最近在编写一个进行视频播放的ActiveX控件,工作已经接近尾声,现将其中显示YUV数据的使用DirectDraw的一些经验总结如下:(解码部分不是我编写的,我负责从网络接收数据,将数据传给解码器,并 ...
- 高级DirectDraw
使用高彩模式 上一章中说了可以用16位的色彩深度,但是16位的色彩深度的数据表示模式可以有两种:Alpha.5.5.5(or X.5.5.5) 和 5.6.5(这是16位色彩最常用的).对于使用哪种1 ...
- 第16月第6天 vs2005 lseek directdraw
1. //_lseek(file_handle, -(int)pbitmap->bitmapinfoheader.biSizeImage, SEEK_END); SetFilePointer(( ...
- DirectX - dds图片格式(DDSURFACEDESC2)
DDS是DirectDraw Surface的缩写,它是DirectX纹理压缩(DirectX Texture Compression,简称DXTC)的产物. DXTC减少了纹理内存消耗的50%甚至更 ...
- DirectDraw打造极速图形引擎(Alpha混合)
显然DirectDraw是Windows下写2D图形程序的最好选择,虽然Direct3D也可以写,但是没DirectDraw简单方便,特别对于初学者,一来就接触那么多函数和参数总不是件愉快的事,所以我 ...
随机推荐
- win10下端口被占用解决办法
调试socket通信的时候,如果程序未正常结束,重新启动会报端口被占用的错误. 一 查找被占用的端口 解决办法如下:按win+R输入cmd打开控制台,输入 netstat -ano|findstr 8 ...
- Date对象和正则对象
1.Date对象 创建 var date1 = new Date(); var date2 = new Date(12983798123);//填一个毫秒值,应该是距离1970年1月1日.....多少 ...
- 二目运算符 “->”
-> 在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符“.”.用法:p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员.表达式p->a引用了指针p指向 ...
- 单元测试系列:如何使用JUnit+JaCoCo+EclEmma完成单元测试
更多原创测试技术文章同步更新到微信公众号 :三国测,敬请扫码关注个人的微信号,感谢! 原文链接:http://www.cnblogs.com/zishi/p/6726664.html -----如 ...
- 以Apache模块的方式编译安装php-5.4.27
为什么要安装低版本的php? 由于apc,xcache的更新版本跟不上php版本的速度,所以,我们需要安装比较稳定的php低版本程序,再安装其它与之相匹配的扩展. 开工: 新建用户及用户组 group ...
- Flask之基于route装饰器的路由系统(源码阅读解析)
一 路由系统 1. 在flask中配置URL和视图函数的路由时,首先需要在main.py中实例化一个app对象: from flask import Flask, render_template ap ...
- python监控接口请求
#!/usr/bin/env python #coding=utf8 import time,os,sched,urllib,httplib import smtplib import string ...
- BZOJ 1923: [Sdoi2010]外星千足虫 [高斯消元XOR]
1923: [Sdoi2010]外星千足虫 对于 100%的数据,满足 N≤1,000,M≤2,000. 裸高斯消元解异或方程组 给定方程顺序要求用从上到下最少的方程,那么找主元时记录一下最远找到哪个 ...
- BZOJ 2467: [中山市选2010]生成树 [组合计数]
2467: [中山市选2010]生成树 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 638 Solved: 453[Submit][Status][ ...
- 自兴人工智能-------------Python入门基础(1)
Python 是一门简单易学且功能强大的编程语言. 它拥有高效的高级数据结构, 并且能够用简单而又高效的方式进行面向对象编程. Python 优雅的语法和动态 类型,再结合它的解释性,使其在大多数平台 ...