Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
24 KiB

  1. Pluggable Software Rasterizer
  2. (c) Microsoft 2000
  3. D3D8 now allows applications to register specific software rasterizers as
  4. a software device, also known as pluggable software rasterizers. Only one
  5. rasterizer can be registered with each Direct3D object, and then cannot be
  6. unregisted.
  7. The rasterizer is registered with a call to
  8. IDirect3D8::RegisterSoftwareDevice, and then devices are created with calls
  9. to IDirect3D8::CreateDevice by passing in D3DDEVTYPE_SW. The void* parameter
  10. to IDirect3D8::RegisterSoftwareDevice is a pointer to a function, typically
  11. named D3D8GetSWInfo.
  12. HRESULT APIENTRY D3D8GetSWInfo( D3DCAPS8* pCaps, PD3D8_SWCALLBACKS pCallbacks,
  13. DWORD* pNumTextures, DDSURFACEDESC** ppTexList);
  14. This primary entry point is used to retrieve the caps that the device
  15. supports, the secondary entry points/ callbacks, and a list of supported render
  16. surfaces/ textures. This function should be expected to be called multiple
  17. times; but the returning parameters should never change. See the sample, D3D
  18. headers, SDK & DDK documentation for descriptions of D3DCAPS8 and supported
  19. surface lists. Many of the secondary entry points/ callbacks are unused due
  20. to an aging API. The required list of entry points is as follows:
  21. DWORD APIENTRY CreateSurface( LPDDHAL_CREATESURFACEDATA pData);
  22. DWORD APIENTRY CreateSurfaceEx( LPDDHAL_CREATESURFACEEXDATA pData);
  23. DWORD APIENTRY DestroySurface( LPDDHAL_DESTROYSURFACEDATA pData);
  24. DWORD APIENTRY Lock( LPDDHAL_LOCKDATA pData);
  25. DWORD APIENTRY Unlock( LPDDHAL_UNLOCKDATA pData);
  26. DWORD APIENTRY ContextCreate( LPD3DHAL_CONTEXTCREATEDATA pData);
  27. DWORD APIENTRY ContextDestroy( LPD3DHAL_CONTEXTDESTROYDATA pData);
  28. DWORD APIENTRY DrawPrimitives2( LPD3DHAL_DRAWPRIMITIVES2DATA pData);
  29. Each of these callbacks has some documentation in the DDK help. But, in
  30. essence, CreateSurface and DestroySurface must allocate and destroy
  31. "video memory" or "driver allocated" surfaces, textures, vertex buffers, etc.
  32. CreateSurfaceEx is used to update the driver on the existence of system
  33. memory surfaces and complex attachment arrangements. Lock and Unlock request
  34. the driver to lock and unlock "video memory" or "driver allocated" surfaces.
  35. ContextCreate and ContextDestroy must allocate and destroy device contexts.
  36. DrawPrimitives2 is a complex callback which requires a context to parse a
  37. command buffer to manipulate render states and rasterize primitives.
  38. The DX8SDDI framework provides templated classes, which provide a design mix
  39. between STL and ATL. This provides a highly componentized and extendable
  40. programming framework without much performance penalty, as long as the compiler
  41. is able to efficiently compile STL objects or inline deeply. In the spirit of
  42. generic programming, there are 5 major concepts that make up the driver
  43. framework: Driver, PerDDrawData, SurfDBEntry, Surface, and Context. Typically,
  44. as in ATL, to create one's own Driver concept class, a developer would inherit
  45. from CSubDriver with the parent class a template parameter of the CSubDriver.
  46. For ex:
  47. class CMyDriver:
  48. public CSubDriver< CMyDriver, ... >
  49. {
  50. };
  51. This allows the CSubDriver to call supplied or overriden functions provided
  52. by CMyDriver without the performance penalty of virtual functions. The naming
  53. convention of the base implementation is always CSub*****, such as CSubDriver,
  54. CSubPerDDrawData, and CSubContext. Sometimes, all the functions provided by
  55. a CSub***** base class is all that is needed. Since a CSub***** base class
  56. cannot be created without deriving from it, there is another naming convention
  57. for the classes which have such a minimal implementation. They are named
  58. CMinimal***** classes, such as CMinimalPerDDrawData. All these classes do is
  59. derive from the CSub***** base class and publicize the constructor and
  60. destructor. The CMinimalDriver is an exception to this rule, as it can't be
  61. created directly either. A unique driver class must be created and inherit
  62. even from CMinimalDriver< * >.
  63. For ex:
  64. template< class TD>
  65. class CMinimalPerDDrawData:
  66. public CSubPerDDrawData< CMinimalPerDDrawData< TD>, TD>
  67. {
  68. public:
  69. CMinimalPerDDrawData( TD& Driver, DDRAWI_DIRECTDRAW_LCL& DDLcl)
  70. :CSubPerDDrawData< CMinimalPerDDrawData< TD>, TD>( Driver, DDLcl)
  71. { }
  72. ~CMinimalPerDDrawData()
  73. { }
  74. };
  75. Note, CMinimalPerDDrawData still needs to know the concept class of the
  76. Driver, so that it can store a local reference back to it. Therefore, it
  77. still has a template parameter which requires the type of Driver, TD. This
  78. could be CMinimalDriver, a class derived from CSubDriver, or a completely
  79. custom class which still conforms to the concept of Driver. This way a
  80. developer can replace each component of the entire driver as need be without
  81. modifying the other components.
  82. /------------------------------------------------------------------------------\
  83. |
  84. | Driver
  85. |
  86. \------------------------------------------------------------------------------/
  87. The first concept is the Driver class. This class handles direct interaction
  88. of mapping the primary and secondary entry points from the SDDI to the
  89. appropriate concept objects. It also enforces the restriction of only one
  90. Driver class per process. The CSubDriver class provides a static pointer to
  91. the one and only Driver in the process and provides a GetSWInfo function
  92. which has to be called by a "bridge" function. The pointer to this bridge
  93. function is what should be passed to IDirect3D8::RegisterSoftwareDevice. Also,
  94. the static variable must be defined somewhere, or the compiler will error.
  95. For ex, in the sample:
  96. class CMyDriver:
  97. public CMinimalDriver< CMyDriver, CMyRasterizer>
  98. {
  99. ...
  100. };
  101. // Define static variable and initialize to NULL.
  102. CMyDriver* CMyDriver::sm_pGlobalDriver= NULL;
  103. // Somewhere the class must be created. A global class is dangerous, because
  104. // C++ doesn't guarentee creation order of global/ static data. There is some
  105. // global data which might not be created before the driver does which should
  106. // be. So, it is safer to create the class within main. Otherwise, a global
  107. // class is possible if construction order doesn't matter:
  108. //
  109. // CMyDriver g_GlobalDriver;
  110. // CMyDriver* CMyDriver::sm_pGlobalDriver= &g_GlobalDriver;
  111. //
  112. BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved)
  113. {
  114. switch( dwReason)
  115. {
  116. case( DLL_PROCESS_ATTACH):
  117. try {
  118. CMyDriver::sm_pGlobalDriver= new CMyDriver;
  119. } catch( ... ) {
  120. // This can catch any constructor execeptions
  121. // as well as bad_alloc.
  122. }
  123. if( NULL== CMyDriver::sm_pGlobalDriver)
  124. return FALSE;
  125. break;
  126. case( DLL_PROCESS_DETACH):
  127. if( NULL!= CMyDriver::sm_pGlobalDriver)
  128. delete CMyDriver::sm_pGlobalDriver;
  129. CMyDriver::sm_pGlobalDriver= NULL;
  130. break;
  131. }
  132. return TRUE;
  133. }
  134. // Bridge function which calls the Driver object's GetSWInfo. D3D8GetSWInfo
  135. // should be passed into RegisterSoftwareDevice.
  136. HRESULT APIENTRY
  137. D3D8GetSWInfo( D3DCAPS8* pCaps, PD3D8_SWCALLBACKS pCallbacks,
  138. DWORD* pNumTextures, DDSURFACEDESC** ppTexList)
  139. {
  140. return CMyDriver::sm_pGlobalDriver->GetSWInfo( *pCaps, *pCallbacks,
  141. *pNumTextures, *ppTexList );
  142. }
  143. The Driver concept class exposes the following types: TDriver, TContext,
  144. TPerDDrawData, TSurface, as well as a few others. The Driver contains a STL
  145. vector of TContext*s, which tracks all instances of Contexts; and a STL vector
  146. of TSurface*s, which tracks all instances of Surfaces or driver allocated
  147. surfaces. The Driver also contains a STL map associating a
  148. LPDDRAWI_DIRECTDRAW_LCL to a TPerDDrawData. The Driver also maps the secondary
  149. entry points to their respective concept objects.
  150. -CreateSurface
  151. This entry point is requesting the driver to allocate a "video memory" or
  152. "driver allocated" surface. This is equivalent to new TSurface;. However, the
  153. creation is actually done by a surface allocator object which can, naturally,
  154. be replaced: TSurfAlloc.
  155. -DestroySurface
  156. This entry point is requesting the driver to deallocate a "video memory" or
  157. "driver allocated" surface. This is equivalent to delete TSurface;
  158. -CreateSurfaceEx
  159. This entry point is notifing the driver of "system memory" surface and
  160. "video memory" surface creation and destruction. This is the point where each
  161. surface gets assigned a DWORD handle, except "video memory" surfaces already
  162. know theirs from CreateSurface. The Driver passes this to
  163. TPerDDrawData::SurfaceCreated and TPerDDrawData::SurfaceDestroyed which will
  164. update the Surface Database with information about surfaces, their attachment
  165. heirarchy, and their DWORD handle.
  166. -Lock
  167. This entry point is requesting the driver to lock a "video memory" or
  168. "driver allocated" surface. The Driver maps this to TSurface::Lock,
  169. which returns the pointer to the surface bits.
  170. -Unlock
  171. This entry point is requesting the driver to unlock a "video memory" or
  172. "driver allocated" surface. The Driver maps this to TSurface::Unlock.
  173. -ContextCreate
  174. This entry point is requesting the driver to allocate a device context.
  175. This is equivalent to new TContext.
  176. -ContextDestroy
  177. This entry point is requesting the driver to deallocate a device context.
  178. This is equivalent to delete TContext;
  179. -DrawPrimitives2
  180. This entry point contains all the instructions to change render states and
  181. rasterize primitives. It is mapped directly to the corresponding
  182. TContext::DrawPrimitves2.
  183. -ValidateTextureStageState
  184. This entry point is slightly optional as it is directly called by an
  185. application. Since the application knows whether it calls
  186. IDirect3DDevice8::ValidateDevice, it can appropriately add code for
  187. ValidateTextureStageState. For maximum compatability, it is suggested to
  188. have this implemented. The Driver maps this call to the corresponding
  189. TContext::ValidateTextureStageState.
  190. -GetDriverState
  191. This entry point is slightly optional as it is directly called by an
  192. application. Since the application knows whether it calls
  193. IDirect3DDevice8::GetInfo, it can appropriately add code for GetDriverState.
  194. For maximum compatability, it is suggested to have this implemented. The
  195. Driver maps this call to the corresponding TContext::GetDriverState.
  196. If any other entry points or callbacks are called which do not have a default
  197. implementation, an assert will fire in debug mode. Then, a developer can
  198. override the insufficient entry point CSubDriver provides.
  199. /------------------------------------------------------------------------------\
  200. |
  201. | PerDDrawData and SurfDBEntry
  202. |
  203. \------------------------------------------------------------------------------/
  204. The second concept is the PerDDrawData class. This appropriately named class
  205. really just stores any information which should be associated with a SDDI
  206. DDraw object (DDRAWI_DIRECTDRAW_LCL). Typically, it is considered invalid to
  207. store pointers to DDRAWI***** objects; and even worse to read or write from this
  208. pointer outside of the callback context which it was passed into. However, it
  209. is allowable to store a pointer to DDRAWI_DIRECTDRAW_LCL to make the distinction
  210. of "per DDraw" in the sense used here. There can be multiple DDraw objects
  211. when multiple Direct3D8 objects are created. If the same driver is registered
  212. with each Direct3D8 objects, then multiple DDraw objects will be exposed to
  213. the driver. The PerDDrawData class needs to contain a database of DWORD
  214. surface handles to information about the surface for the Context.
  215. For example, if the application specifies IDirect3DDevice8::SetTexture,
  216. the SW device, known by us as a Context concept, needs to be able to at least
  217. get the lpVidMem pointer to the surface bits from the DWORD passed into
  218. SetTexture. The Context will also need to be able to extract other information
  219. from the DWORD, like pixel format, width, height, etc., especially for "system
  220. memory" surfaces. All this information is stored in the PerDDrawData surface
  221. database. This must be, because the DWORD handles are unique per DDraw object.
  222. So, the driver must be able to convert a LPDDRAWI_DIRECTDRAW_LCL and DWORD
  223. surface handle to information about the surface for the Context.
  224. The PerDDrawData exposes the following types: TDriver and the third concept,
  225. TSurfDBEntry. The PerDDrawData contains a surface database which is a STL map
  226. which associates DWORD surface handles to TSurfDBEntry objects, which contain
  227. information about the surface. The PerDDrawData must implement SurfaceCreated
  228. and SurfaceDestroyed for the Driver to call. It must also implement GetDriver
  229. and GetSurfDBEntry for the Context to use.
  230. Note that there should be at least as many TSurfDBEntry objects as there are
  231. TSurface objects. This is because the SDDI will notify the driver of the
  232. surface characteristics and attachment configuration of any "system memory"
  233. surfaces and any "video memory" surface belonging to the driver. This is the
  234. only way the driver can figure out the attachment configuration of "video
  235. memory" surfaces.
  236. The Driver object knows how to navigate from a DDRAWI_DDRAWSURFACE_LCL object
  237. and a SurfDBEntry object to a Surface object. Each Surface object also has a
  238. DWORD surface handle field which allows one to find the associated SurfDBEntry
  239. object by looking up the handle in the PerDDrawData.
  240. The typical SurfDBEntry contains accessor functions named similar to the
  241. data stored in the DDRAWI_DDRAWSURFACE_LCL. For example, the CSurfDBEntry
  242. exposes:
  243. GetLCLdwFlags() == DDRAWI_DDRAWSURFACE_LCL::dwFlags
  244. GetLCLddsCaps() == DDRAWI_DDRAWSURFACE_LCL::ddsCaps
  245. GetMOREddsCapsEx() == DDRAWI_DDRAWSURFACE_MORE::ddsCapsEx
  246. GetGBLfpVidMem() == DDRAWI_DDRAWSURFACE_GBL::fpVidMem
  247. etc.
  248. /------------------------------------------------------------------------------\
  249. |
  250. | Surface
  251. |
  252. \------------------------------------------------------------------------------/
  253. The fourth concept is the Surface class. This represents a "video memory" or
  254. "driver allocated" surface, eventhough "video memory" doesn't accurately
  255. represent the reality. Typically, the driver will want to create multiple
  256. classes which implemented a common ISurface interface either based on pixel
  257. format or surface role. This is because the Driver object needs to be able to
  258. lock and unlock each surface. The default implementation of Surface is an
  259. interface, IVidMemSurface. This means that when the Driver maps the Lock and
  260. Unlock entry points to TSurface::Lock and TSurface::Unlock, the Driver is
  261. actually calling a virtual function. Also, the Context concept class need to
  262. be able to Clear all render targets. Therefore, the IVidMemSurface interface
  263. includes a Clear function. Thus, the Context is also calling a virtual Clear
  264. function to clear a surface. A developer adding "video memory" textures to the
  265. framework can implement a trivial IVidMemSurface::Clear for these textures by
  266. asserting false and returning failure. This is because non-render targets
  267. should never be cleared.
  268. Nothing prevents the developer from removing the interface, and using a
  269. purely generic surface class. But, it was expected that the more common
  270. scenario would be to provide an interface here.
  271. As indicated before, the Surface class needs to implement Lock and Unlock
  272. for the Driver and Context to call. The Context also needs to be able to call
  273. Clear.
  274. /------------------------------------------------------------------------------\
  275. |
  276. | Context
  277. |
  278. \------------------------------------------------------------------------------/
  279. The final, fifth main concept is the Context class. This represents the
  280. object which implements the IDirect3DDevice8 interface to the application.
  281. The primary functions which it needs to implement is DrawPrimitves2 and
  282. optionally, ValidateTextureStageState. This is the most complex concept class
  283. there is and the implementation was broken up into multiple classes, to again
  284. provide a maxmimum amount of componentization and extendability.
  285. The entry point DrawPrimitives2 needs to parse a command buffer for
  286. individual commands and execute them. Whatever parses the command buffer also
  287. needs to be aware of state sets. See DDK documentation for a description.
  288. The default implementation for DrawPrimitives2 is CStdDrawPrimitives2. It is
  289. expected that the Context will inherit from CStdDrawPrimitives2 if its
  290. implementation is wanted.
  291. CStdDrawPrimitives2::DrawPrimitives2 first wraps the
  292. D3DHAL_DRAWPRIMITIVES2DATA class with a class that exposes the command
  293. buffer as a STL container complete with iterators. It uses a Parser
  294. function to call a member function corresponding to each D3DHAL_DP2COMMAND.
  295. The naming convention for these Context member functions are DP2*****. The
  296. CStdDrawPrimitives2 also takes care of state sets. In order to handle state
  297. set recording and capturing, CStdDrawPrimitives2 uses another Parser to call
  298. a recording member function corresponding to each D3DHAL_DP2COMMAND. The
  299. naming convention for these Context member functions are RecDP2*****.
  300. There are also classes which implement many of the required DP2***** and
  301. RecDP2***** functions. So, inheriting from CStdDrawPrimitives2 should be seen
  302. as providing the Context with an implementation for DrawPrimitives2, but also
  303. as seen as needing implementations for many DP2 commands, implementations for
  304. recording many DP2 commands, a collection of DP2Operations <=> member function
  305. bindings, and a collection of DP2Operations <=> recording member function
  306. bindings. For example, let's examine a new CMyContext:
  307. class CMyContext:
  308. public CSubContext< CMyContext, ... >
  309. {
  310. };
  311. CMyContext still has no DrawPrimitives2 entry point. CSubContext exposes
  312. the following types: TDriver, TSurface, TPerDDrawData, and TDP2Data.
  313. CSubContext stores a reference to the corresponding PerDDrawData, and
  314. the render target and zbuffer surface pointers. The render target and
  315. zbuffer are TSurface*, not TSurfDBEntry*, as render targets must be
  316. "driver allocated". CSubContext also provides a few functions, like
  317. GetPerDDrawData, DP2SetRenderTarget, and DP2Clear. The last two functions
  318. provide a default implementation to handle the DP2OP_SETRENDERTARGET and
  319. DP2OP_CLEAR commands. However, nothing uses these functions yet.
  320. // Forward declaration
  321. class CMyContext;
  322. // For minimal amount of typing/ retyping.
  323. typedef CStdDrawPrimitves2< CMyContext> TStdDrawPrimitves2;
  324. class CMyContext:
  325. public TStdDrawPrimitves2,
  326. public CSubContext< CMyContext, ... , TStdDrawPrimitves2::TDP2Data >
  327. {
  328. };
  329. Now, CMyContext has a DrawPrimitives2 entry point for the Driver to call,
  330. which is provided by CStdDrawPrimitives2. CMyContext also has default support
  331. for DP2OP_SETRENDERTARGET, DP2OP_CLEAR; but CStdDrawPrimitives2 doesn't have
  332. information on which member function to call for each DP2 command. Note that
  333. TDP2Data is used as a template parameter for CSubContext. This is because
  334. the first paramter of the DP2***** member functions is templatized for
  335. extendability reasons. For CSubContext's DP2SetRenderTarget and DP2Clear
  336. to have the same parameter types as CStdDrawPrimitives2 can call, this is
  337. needed.
  338. // Forward declaration
  339. class CMyContext;
  340. // For minimal amount of typing/ retyping.
  341. typedef CStdDrawPrimitves2< CMyContext> TStdDrawPrimitves2;
  342. class CMyContext:
  343. public TStdDrawPrimitves2,
  344. public CSubContext< CMyContext, ... , TStdDrawPrimitves2::TDP2Data >
  345. {
  346. public:
  347. typedef block< TStdDrawPrimitives2::TDP2CmdBind, 2> TDP2Bindings;
  348. protected:
  349. static const TDP2Bindings c_DP2Bindings;
  350. public:
  351. CMyContext( ... )
  352. :TStdDrawDrimitives2( c_DP2Bindings.begin(), c_DP2Bindings.end()),
  353. CSubContext< CMyContext>( ... )
  354. { }
  355. };
  356. const CMyContext::TDP2Bindings CMyContext::c_DP2Bindings=
  357. {
  358. D3DDP2OP_SETRENDERTARGET, DP2SetRenderTarget,
  359. D3DDP2OP_CLEAR, DP2Clear
  360. };
  361. Now, CMyContext has provided CStdDrawPrimitives2 with a collection of
  362. bindings. CStdDrawPrimitives2 will now call CMyContext::DP2SetRenderTarget,
  363. which is really CSubContext< CMyContext, ... >::DP2SetRenderTarget when
  364. a DP2 command with D3DDP2OP_SETRENDERTARGET is encountered. There are
  365. other classes which can provide default implementations for each DP2
  366. operation and have the naming convention CStdDP2*****, like
  367. CStdDP2RenderStateStore, which provides DP2RenderState and RecDP2RenderState.
  368. Also, any CStdDP2*****Store class really just stores the parameters of the
  369. command for later reference. For example, CStdDP2WInfoStore just
  370. stores the D3DHAL_DP2WINFO data and provides functions so that the Context,
  371. itself, can be converted to D3DHAL_DP2WINFO or can be retrieved by calling
  372. TContext::GetDP2WInfo.
  373. The fully functional CMyContext which exposes 1 stream, no TnL support, and
  374. only legacy pixel shading would look something like:
  375. // Forward declaration
  376. class CMyContext;
  377. // For minimal amount of typing/ retyping.
  378. typedef CStdDrawPrimitves2< CMyContext> TStdDrawPrimitves2;
  379. // Actually, TStdDrawPrimitives2::TDP2Data can be left out of the template
  380. // parameters for each of the CStdDP2***** classes, as long as the default
  381. // TDP2Data is used from CStdDrawPrimitives2. This is the same default that
  382. // all the other classes have.
  383. class CMyContext:
  384. public TStdDrawPrimitves2,
  385. public CSubContext< CMyContext, ... >,
  386. public CStdDP2ViewportInfoStore< CMyContext>,
  387. public CStdDP2WInfoStore< CMyContext>,
  388. public CStdDP2RenderStateStore< CMyContext>,
  389. public CStdDP2TextureStageStateStore< CMyContext>,
  390. public CStdDP2SetVertexShaderStore< CMyContext>,
  391. public CStdDP2VStreamManager< CMyContext, CVStream< ... > >,
  392. public CStdDP2IStreamManager< CMyContext, CIStream< ... > >
  393. {
  394. public:
  395. typedef block< TStdDrawPrimitives2::TDP2CmdBind, 15> TDP2Bindings;
  396. typedef block< TStdDrawPrimitives2::TRecDP2CmdBind, 7> TRecDP2Bindings;
  397. protected:
  398. static const TDP2Bindings c_DP2Bindings;
  399. static const TRecDP2Bindings c_RecDP2Bindings;
  400. public:
  401. CMyContext( ... )
  402. :TStdDrawDrimitives2( c_DP2Bindings.begin(), c_DP2Bindings.end(),
  403. c_RecDP2Bindings.begin(), c_RecDP2Bindings.end()),
  404. CSubContext< CMyContext>( ... )
  405. { }
  406. };
  407. const CMyContext::TDP2Bindings CMyContext::c_DP2Bindings=
  408. {
  409. D3DDP2OP_VIEWPORTINFO, DP2ViewportInfo,
  410. D3DDP2OP_WINFO, DP2WInfo,
  411. D3DDP2OP_RENDERSTATE, DP2RenderState,
  412. D3DDP2OP_TEXTURESTAGESTATE, DP2TextureStageState,
  413. D3DDP2OP_CLEAR, DP2Clear,
  414. D3DDP2OP_SETRENDERTARGET, DP2SetRenderTarget,
  415. D3DDP2OP_SETVERTEXSHADER, DP2SetVertexShader,
  416. D3DDP2OP_SETSTREAMSOURCE, DP2SetStreamSource,
  417. D3DDP2OP_SETSTREAMSOURCEUM, DP2SetStreamSourceUM,
  418. D3DDP2OP_SETINDICES, DP2SetIndices,
  419. D3DDP2OP_DRAWPRIMITIVE, DP2DrawPrimitive,
  420. D3DDP2OP_DRAWPRIMITIVE2, DP2DrawPrimitive2,
  421. D3DDP2OP_DRAWINDEXEDPRIMITIVE, DP2DrawIndexedPrimitive,
  422. D3DDP2OP_DRAWINDEXEDPRIMITIVE2, DP2DrawIndexedPrimitive2,
  423. D3DDP2OP_CLIPPEDTRIANGLEFAN, DP2ClippedTriangleFan
  424. };
  425. const CMyContext::TRecDP2Bindings CMyContext::c_RecDP2Bindings=
  426. {
  427. D3DDP2OP_VIEWPORTINFO, RecDP2ViewportInfo,
  428. D3DDP2OP_WINFO, RecDP2WInfo,
  429. D3DDP2OP_RENDERSTATE, RecDP2RenderState,
  430. D3DDP2OP_TEXTURESTAGESTATE, RecDP2TextureStageState,
  431. D3DDP2OP_SETVERTEXSHADER, RecDP2SetVertexShader,
  432. D3DDP2OP_SETSTREAMSOURCE, RecDP2SetStreamSource,
  433. D3DDP2OP_SETINDICES, RecDP2SetIndices
  434. };
  435. /------------------------------------------------------------------------------\
  436. |
  437. | Summary
  438. |
  439. \------------------------------------------------------------------------------/
  440. It is expected that a pluggable software rasterizer developer will first
  441. start by defining a CMyRasterizer and a CMyDriver, which derives from
  442. CMinimalDriver just like in the sample to get acquanted with the framework and
  443. verify the plumbing.
  444. The expected next step is to define a CMyContext, which derives from
  445. CSubContext, CStdDrawPrimitives2, & a bunch of CStdDP2*****, just like
  446. CMinimalContext; and a CMyDriver which derives from CSubDriver. The CMyContext
  447. should integrate the old CMyRasterizer functionality.
  448. The expected next step is then to replace CMinimalPerDDrawData with
  449. CMyPerDDrawData, which derives from CSubPerDDrawData; and then start
  450. replacing many of the other components with custom pieces (CSurface,
  451. CStateSet, CSurfDBEntry, CVStream, CIStream, CPalDBEntry, etc).