Leaked source code of windows server 2003
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.

567 lines
16 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // rampmat.hpp
  4. //
  5. // Declares classes for ramp material handling.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #ifndef _RAMPMAT_HPP_
  11. #define _RAMPMAT_HPP_
  12. /* -*- c++ -*- */
  13. #include "rampmap.h"
  14. #include "palette.h"
  15. #include "rgbmap.h"
  16. struct ExtMaterial;
  17. struct IntMaterial;
  18. struct RampMaterial;
  19. struct RLDDIRampLightingDriver;
  20. struct AgeList {
  21. CIRCLE_QUEUE_MEMBER(AgeList) list;
  22. LIST_ROOT(alh,IntMaterial) agelist;
  23. };
  24. class RampCommon {
  25. public:
  26. void* operator new(size_t size)
  27. {
  28. void* p;
  29. if (D3DMalloc(&p, size))
  30. return NULL;
  31. return p;
  32. }
  33. void operator delete(void *p)
  34. {
  35. D3DFree(p);
  36. }
  37. };
  38. /*
  39. * An ExtMaterial is the underlying driver object for an LPDIRECT3DMATERIAL.
  40. * When used, it creates IntMaterials which are distinguished by different
  41. * ambient light, fog, D3DMATERIAL value etc.
  42. *
  43. * The ExtMaterials are kept on a list in the driver and if not explicitly
  44. * freed, they are cleaned up when the driver is destroyed.
  45. *
  46. * The IntMaterials can outlive the ExtMaterial in the case that the
  47. * ExtMaterial is destroyed right after use. We add these orphans to a list
  48. * which is emptied at Clear time since after Clear, no pixels are visible
  49. * which were rendered with the IntMaterial and it can be freed.
  50. */
  51. struct ExtMaterial : public RampCommon {
  52. friend struct IntMaterial;
  53. private:
  54. /*
  55. * Driver object which owns us.
  56. */
  57. RLDDIRampLightingDriver* driver;
  58. /*
  59. * Current API level material definition.
  60. */
  61. D3DMATERIAL mat;
  62. /*
  63. * List of internal materials derived from us.
  64. */
  65. LIST_ROOT(eml,IntMaterial) intlist;
  66. /*
  67. * Generation count. The generation is incremented each time
  68. * the material is changed. This allows us to generate a new internal
  69. * material as needed.
  70. */
  71. int generation;
  72. /*
  73. * This tracks the generation of any texture used by the material. The
  74. * texture generation is bumped if its palette is changed or it is
  75. * loaded from another texture.
  76. */
  77. int texture_generation;
  78. /*
  79. * This tracks the underlying texture object represented by the texture
  80. * handle (if any). If texture handles are swapped, we need to know
  81. * so that we can make a new internal material for the new texture.
  82. */
  83. PD3DI_SPANTEX texture;
  84. /*
  85. * Increment the generation either because the material was set or
  86. * because a texture changed.
  87. */
  88. void Age();
  89. public:
  90. /*
  91. * Chain for list of external materials created by this driver.
  92. */
  93. LIST_MEMBER(ExtMaterial) list;
  94. public:
  95. /*
  96. * Constructor/Destructor.
  97. */
  98. ExtMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat);
  99. ~ExtMaterial();
  100. /*
  101. * Change the API level material.
  102. */
  103. void SetMaterial(D3DMATERIAL* mat);
  104. /*
  105. * Accessor to the current API level material.
  106. */
  107. D3DMATERIAL* GetMaterial() {
  108. return &mat;
  109. }
  110. /*
  111. * Find an internal material which corresponds to the current driver
  112. * object state.
  113. */
  114. IntMaterial* FindIntMaterial();
  115. /*
  116. * Find what range of values lighting should take. The base is the
  117. * pixel value (in fixed point) of the dark end of the material. The
  118. * shift value is user to convert a 0.16 fixed point shade into the
  119. * range needed for the material. e.g.
  120. *
  121. * pixel = base + (VALTOFX8(shade) << shift);
  122. *
  123. */
  124. HRESULT FindLightingRange(unsigned long* base,
  125. unsigned long* size,
  126. BOOL* specular,
  127. unsigned long** texture_colors);
  128. };
  129. /*
  130. * The IntMaterial is derived from an ExtMaterial taking into account the
  131. * driver state when the ExtMaterial was used. Normally IntMaterials are
  132. * on a list in their owning ExtMaterial. If the external material is
  133. * destroyed, any active internal materials which it owned are
  134. * transferred to an orphans list in the driver. This is cleared out
  135. * next time Clear is called.
  136. *
  137. * The internal material has a list of underlying RampMaterials. For
  138. * a non-textured material, there is exactly one and for a textured
  139. * material, there is one per color in the texture's palette. The
  140. * ramp materials track color sharing between internal materials and
  141. * handle the details of allocating color resources.
  142. *
  143. * Internal materials are also chained onto one of a number of lists
  144. * based on their age. The age of a material is the number of frames
  145. * since it was last used to render something. When a material is
  146. * aged, it is rejuvenated by moving it to the age=0 list. Each
  147. * frame, the lists are rotated by one notch and materials on the
  148. * oldest list are reclaimed.
  149. *
  150. * A material is either active or inactive. Active materials have
  151. * color resources and are either on the age=0 list (active this
  152. * frame) or the age=1 list (active last frame). When an inactive
  153. * material is used, it allocates color resources by attempting to
  154. * activate the underlying ramp materials.
  155. *
  156. * At the end of the frame, on Update, any active materials on the
  157. * age=1 list must be materials which were active last frame but were
  158. * not used this frame. We remove their color resources by
  159. * deactivating the underlying ramp materials.
  160. */
  161. struct IntMaterial : public RampCommon {
  162. private:
  163. /*
  164. * Driver object which owns us.
  165. */
  166. RLDDIRampLightingDriver* driver;
  167. /*
  168. * External material which created us.
  169. */
  170. ExtMaterial* extmat;
  171. public:
  172. /*
  173. * Too annoying to have these private.
  174. */
  175. /*
  176. * Chain of internal materials created by our external material owner
  177. * which owns us. The chain is also used to place the material on the
  178. * driver's orphans list if appropriate.
  179. */
  180. LIST_MEMBER(IntMaterial) list;
  181. /*
  182. * Current ageing list which we are on.
  183. */
  184. AgeList* age;
  185. LIST_MEMBER(IntMaterial) agelist;
  186. private:
  187. /*
  188. * D3DMATERIAL which the external material had when it created us.
  189. */
  190. D3DMATERIAL mat;
  191. /*
  192. * TRUE if we are active. We are active if we currently have color
  193. * allocation resources assigned to us.
  194. */
  195. int active;
  196. /*
  197. * Base values of our color allocation resources. Contents are valid
  198. * only when active.
  199. */
  200. unsigned long* colors;
  201. /*
  202. * Features which distinguish us from other internal materials owned by
  203. * our external material.
  204. */
  205. float ambient; // ambient shade
  206. unsigned long viewport_id; // viewport which owns it
  207. int fog_enable; // material incorporates fog
  208. unsigned long fog_color; // the fogging color
  209. int generation;
  210. /*
  211. * RampMaterials used by this internal material.
  212. */
  213. int ramp_count;
  214. RampMaterial** ramps;
  215. public:
  216. /*
  217. * Constructor/Destructor.
  218. */
  219. IntMaterial(ExtMaterial* extmat);
  220. ~IntMaterial();
  221. /*
  222. * Returns TRUE if we match the current settings of our external material
  223. * and driver state.
  224. */
  225. int Valid();
  226. /*
  227. * See ExtMaterial
  228. */
  229. HRESULT FindLightingRange(unsigned long* base,
  230. unsigned long* size,
  231. BOOL* specular,
  232. unsigned long** texture_colors);
  233. /*
  234. * Activate the material and allocate color resources for it.
  235. */
  236. HRESULT Activate();
  237. /*
  238. * Deactivate the material, freeing color resources. Always works.
  239. */
  240. void Deactivate();
  241. /*
  242. * Returns TRUE if the material is currently active.
  243. */
  244. int IsActive() {
  245. return active;
  246. }
  247. /*
  248. * Add the material to the driver's orphaned material list. Called when
  249. * the external material is destroyed.
  250. */
  251. void Orphan();
  252. };
  253. /*
  254. * RampMaterials are used by internal materials to represent ranges of
  255. * colors. They perform low level color allocation by allocating
  256. * color ranges (RLDDIRamps) from a rampmap.
  257. *
  258. * A textured internal material can use many ramp materials.
  259. * Several internal materials can use the same ramp material if the
  260. * colors match. This can happen easily if many textures use the same
  261. * palette. The ramp material maintains a usage of how many internal
  262. * materials are using it and is freed when the last one stops.
  263. *
  264. * Ramp materials, like internal materials are either active or
  265. * inactive. Active materials have color resources and inactive
  266. * materials do not. A ramp material is made active when any of its
  267. * internal material users are active and inactive when none of then
  268. * are active. To track this a count of how many active users is
  269. * maintained.
  270. *
  271. * When a material is made active, it attempts to allocate a color
  272. * range to use. If that is successful, it sets the colors in the
  273. * range to an appropriate ramp of colors. If is no more space in the
  274. * colormap for a new range, it finds the closes active ramp material
  275. * and shares its ramp.
  276. *
  277. * To track active materials and sharing materials, the driver has a
  278. * list of active materials and each material has a list of sharers.
  279. * The sharers list is only valid for materials which are both active
  280. * and which own their ramp.
  281. */
  282. struct RampMaterial : public RampCommon {
  283. private:
  284. /*
  285. * Driver object which owns us.
  286. */
  287. RLDDIRampLightingDriver* driver;
  288. /*
  289. * List of materials which have the same hash value.
  290. */
  291. LIST_MEMBER(RampMaterial) hash;
  292. /*
  293. * Materials sharing this ramp. Only valid for active materials
  294. * with owner == TRUE.
  295. */
  296. LIST_ROOT(name6,RampMaterial) sharers;
  297. /*
  298. * If the material is active, then it is on the drivers rmactive list
  299. * if it owns the ramp, otherwise it is on the sharers list of the
  300. * material which does own the ramp. Only valid for active materials.
  301. */
  302. LIST_MEMBER(RampMaterial) list;
  303. /*
  304. * If were sharing a ramp and inherit it from the owner, we need to
  305. * defer setting the colors until the next frame to avoid possible
  306. * palette flashing. The driver has a list of materials for which
  307. * color setting is deferred, chainged through here.
  308. *
  309. * We make sure that deferredlist.le_next is NULL unless we are
  310. * actually on the deferred list so that we can avoid list problems
  311. * if we are destroyed or passed on to another inheritor before the
  312. * list is processed.
  313. */
  314. LIST_MEMBER(RampMaterial) deferredlist;
  315. /*
  316. * A count of the number of internal materials which use us.
  317. */
  318. int usage;
  319. /*
  320. * A count of active internal materials which use us.
  321. */
  322. int active;
  323. /*
  324. * If we are active (active > 0), this is the underlying color
  325. * range for the material.
  326. */
  327. RLDDIRamp* ramp;
  328. /*
  329. * TRUE if we created or inherited the ramp. FALSE if I am merely
  330. * sharing some other material.
  331. */
  332. int owner;
  333. /*
  334. * Distinguishing features.
  335. */
  336. float ambient; /* ambient shade */
  337. D3DMATERIAL mat; /* material we represent */
  338. int fog_enable; /* material incorporates fog */
  339. unsigned long fog_color; /* the fogging color */
  340. private:
  341. /*
  342. * Constructor/Destructor.
  343. * These are private. Callers should use Find/Release.
  344. */
  345. RampMaterial(RLDDIRampLightingDriver* driver,
  346. D3DMATERIAL* mat, float ambient);
  347. ~RampMaterial();
  348. public:
  349. /*
  350. * Find a material which matches the api material and driver state.
  351. * If no such material exists, make one.
  352. */
  353. static RampMaterial* Find(RLDDIRampLightingDriver* driver,
  354. D3DMATERIAL* mat);
  355. private:
  356. /*
  357. * Next functions are implementation detail of Find.
  358. */
  359. /*
  360. * Compare two api materials to see if they are identical.
  361. */
  362. static int MaterialSame(D3DMATERIAL* mat1, D3DMATERIAL* mat2);
  363. /*
  364. * Return a measure of how close two rgb colors are in rgb space.
  365. */
  366. static int RGBDist(D3DCOLORVALUE* rgb1, D3DCOLORVALUE* rgb2);
  367. /*
  368. * Return a measure of how close two api materials are.
  369. */
  370. static int CompareMaterials(D3DMATERIAL* mat1, D3DMATERIAL* mat2);
  371. public:
  372. /*
  373. * Called by a user when it is no longer needed.
  374. */
  375. void Release();
  376. /*
  377. * Called by a user when the material is about to be used.
  378. */
  379. HRESULT Activate();
  380. /*
  381. * Called by a user when the material has not been used this frame.
  382. */
  383. void Deactivate();
  384. /*
  385. * Return the base color of an active material.
  386. */
  387. unsigned long Base();
  388. private:
  389. /*
  390. * Implementation details of Activate and Deactivate.
  391. */
  392. /*
  393. * Allocate a ramp of colors for us to use.
  394. * May only be called for an inactive material.
  395. */
  396. HRESULT AllocateColors();
  397. /*
  398. * Free our color allocation. May only be called for an active material.
  399. */
  400. void FreeColors();
  401. /*
  402. * Set the color values of our color allocation.
  403. */
  404. private:
  405. void SetColorsStd();
  406. void SetColorsFog();
  407. public:
  408. void SetColors();
  409. };
  410. ///*
  411. // * Workspace used when evaluating complex lighting models.
  412. // */
  413. //struct Workspace {
  414. // float diffuse;
  415. // float specular;
  416. //};
  417. //
  418. //struct SpecularTable {
  419. // LIST_MEMBER(SpecularTable) list;
  420. // float power; /* shininess power */
  421. // float table[260]; /* space for overflows */
  422. //};
  423. //
  424. //#define WORKSPACE_SIZE 1024
  425. #define HASH_SIZE 257
  426. /*
  427. * If the app is rendering at 30fps, this means that a material can survive
  428. * for about 5 seconds. This seems like enough to cope with stuff moving
  429. * out of shot and back in again soon after.
  430. */
  431. #define AGE_MAX (30*5) /* age at which unused materials die */
  432. typedef struct _RLDDISoftLightingDriver {
  433. D3DMATERIAL material;
  434. float ambient;
  435. D3DFOGMODE fog_mode;
  436. float fog_start;
  437. float fog_end;
  438. float fog_density;
  439. D3DMATERIALHANDLE hMat;
  440. D3DCOLORMODEL color_model;
  441. DWORD ambient_save;
  442. } RLDDISoftLightingDriver;
  443. struct RLDDIRampLightingDriver {
  444. RLDDISoftLightingDriver driver; /* common fields */
  445. /*
  446. * Colormap
  447. */
  448. RLDDIPalette* palette;
  449. RLDDIRGBMap* rgbmap;
  450. unsigned long* pixelmap; /* map color indices to pixels */
  451. PALETTEENTRY ddpalette[256];
  452. int paletteChanged;
  453. RLDDIRampmap* rampmap;
  454. unsigned long viewport_id; /* current viewport */
  455. int fog_enable;
  456. unsigned long fog_color;
  457. /*
  458. * External materials created by this driver.
  459. */
  460. LIST_ROOT(deml,ExtMaterial) materials;
  461. /*
  462. * Active internal materials orphaned by their owning external material.
  463. */
  464. LIST_ROOT(diml,IntMaterial) orphans;
  465. AgeList agelists[AGE_MAX];
  466. CIRCLE_QUEUE_ROOT(aqh,AgeList) agequeue; /* age sorted queue of lists */
  467. AgeList* active; /* current active list */
  468. /*
  469. * This is set to TRUE after Clear has advanced the ages one notch and
  470. * cleared on update. It is used to stop multiple calls to Clear from
  471. * confusing the aging system
  472. */
  473. int already_aged;
  474. LIST_ROOT(name7,RampMaterial) rmactive; /* materials with ramps */
  475. LIST_ROOT(name8,RampMaterial) rmdeferred;
  476. LIST_ROOT(name9,RampMaterial) hash[HASH_SIZE]; /* materials hash table */
  477. /*
  478. * Current material.
  479. */
  480. ExtMaterial* current_material;
  481. };
  482. typedef struct _RLDDILookupMaterialData {
  483. D3DMATERIALHANDLE hMat; /* material to look up */
  484. unsigned long base; /* base pixel value */
  485. unsigned long size; /* size of index range */
  486. unsigned long texture_index; /* texture table for textures */
  487. } RLDDILookupMaterialData;
  488. #endif // _RAMPMAT_HPP_