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.

2048 lines
63 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // rmprov.cpp
  4. //
  5. // Declares classes for ramp material handling.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. include(`m4hdr.mh')dnl
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. //#define _D3DHAL_H_
  14. //typedef void* LPD3DHAL_CALLBACKS;
  15. //typedef void* LPD3DHAL_CALLBACKS2;
  16. //typedef void* LPD3DHAL_TRANSFORMLIGHTCALLBACKS;
  17. //typedef void* LPD3DHAL_TEXTURE3CALLBACKS;
  18. //typedef void* LPD3DHAL_GLOBALDRIVERDATA;
  19. //typedef void* LPD3DHAL_D3DEXTENDEDCAPS;
  20. //
  21. //#include <assert.h>
  22. //#include <string.h>
  23. //#include <math.h>
  24. //
  25. //extern "C" {
  26. //#include "driver.h"
  27. //#include "lightdrv.h"
  28. //#include "fsqrt.h"
  29. //#include "lists.h"
  30. //#include "ramplt.h"
  31. //#include "rampmap.h"
  32. //#include "transfm.h"
  33. //#include "handle.h"
  34. //#include "gentex.h"
  35. //#include "dmath.h"
  36. //#include "ramplti.h"
  37. //#include "dpf.h"
  38. //
  39. //#include <d3di.h>
  40. //#include "..\include\genras.h"
  41. //}
  42. //
  43. //static void Destroy(RLDDIDriver* drv);
  44. //static long RampLightingService(RLDDIDriver* drv, RLDDIServiceType type,
  45. // long arg1, void* arg2);
  46. //
  47. //#define SPEC(tab, s) tab->table[QVALTOFXP(s, 8)]
  48. //#define NEXT_X(type, x, size) ((type*)((char*) (x) + (size)))
  49. //#define NEXT_ELEMENT(el, size) NEXT_X(D3DLIGHTINGELEMENT, el, size)
  50. //#define NEXT_COLOR(col, size) NEXT_X(unsigned long, col, size)
  51. //#define NEXT_VERTEX(v, size) NEXT_X(D3DTLVERTEX, v, size)
  52. //
  53. #define CVAL_TO_RGBA(rgb) RGBA_MAKE((int)(255.0 * (rgb)->r), \
  54. (int)(255.0 * (rgb)->g), \
  55. (int)(255.0 * (rgb)->b), \
  56. (int)(255.0 * (rgb)->a))
  57. //static HRESULT LitFog(RLDDIRampLightingDriver* driver,
  58. // int count, D3DTLVERTEX* v, size_t v_size,
  59. // Workspace* wp);
  60. static void ReclaimMaterials(RLDDIRampLightingDriver* driver);
  61. //void vectordvNormalise12(D3DVECTOR* v);
  62. //
  63. //static D3DCOLOR cval_to_cola(D3DCOLORVALUE* rgb)
  64. //{
  65. // return CVAL_TO_RGBA(rgb);
  66. //}
  67. //
  68. static int InitRampmap(PD3DI_RASTCTX pCtx, RLDDIRampLightingDriver* driver, RLDDIRampmap** rampmap_return)
  69. {
  70. RLDDIColormap* cmap;
  71. RLDDIRampmap* rampmap;
  72. RLDDIColorAllocator* alloc;
  73. LPDDRAWI_DDRAWSURFACE_LCL pLcl =
  74. ((LPDDRAWI_DDRAWSURFACE_INT)(pCtx->pDDS))->lpLcl;
  75. if ((pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE4) || (pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE8))
  76. {
  77. if (pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE4)
  78. {
  79. driver->palette = RLDDICreatePalette(pCtx, 16);
  80. }
  81. else
  82. {
  83. driver->palette = RLDDICreatePalette(pCtx, 256);
  84. }
  85. alloc = &driver->palette->alloc;
  86. // Initialize palette
  87. PALETTEENTRY ddppe[256];
  88. HRESULT ddrval;
  89. LPDIRECTDRAWPALETTE lpPal;
  90. ddrval = pCtx->pDDS->GetPalette(&lpPal);
  91. ddrval = lpPal->GetEntries(0, 0, 256, ddppe);
  92. memset(driver->ddpalette, 0, sizeof(PALETTEENTRY) * 256);
  93. for (int i = 0; i < 256; i++) {
  94. DWORD dwFlags = ddppe[i].peFlags & (D3DPAL_FREE | D3DPAL_READONLY | D3DPAL_RESERVED);
  95. driver->ddpalette[i].peFlags = ddppe[i].peFlags;
  96. switch (dwFlags) {
  97. case D3DPAL_FREE:
  98. D3D_INFO(6, "(Rast) Color %d is free", i);
  99. RLDDIPaletteFreeColor(driver->palette, i);
  100. break;
  101. case D3DPAL_READONLY:
  102. D3D_INFO(6, "(Rast) Color %d is readonly", i);
  103. RLDDIPaletteSetColor(driver->palette, i,
  104. ddppe[i].peRed, ddppe[i].peGreen, ddppe[i].peBlue);
  105. driver->ddpalette[i].peRed = ddppe[i].peRed;
  106. driver->ddpalette[i].peGreen = ddppe[i].peGreen;
  107. driver->ddpalette[i].peBlue = ddppe[i].peBlue;
  108. break;
  109. case D3DPAL_RESERVED:
  110. D3D_INFO(6, "(Rast) Color %d is reserved", i);
  111. break;
  112. default:
  113. D3D_ERR("(Rast) Unknown flag passed in peFlags");
  114. break;
  115. }
  116. }
  117. }
  118. else
  119. {
  120. DWORD dwRMask, dwGMask, dwBMask;
  121. if (pLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  122. {
  123. dwRMask = pLcl->lpGbl->ddpfSurface.dwRBitMask;
  124. dwGMask = pLcl->lpGbl->ddpfSurface.dwGBitMask;
  125. dwBMask = pLcl->lpGbl->ddpfSurface.dwBBitMask;
  126. }
  127. else
  128. {
  129. dwRMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwRBitMask;
  130. dwGMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwGBitMask;
  131. dwBMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwBBitMask;
  132. }
  133. driver->rgbmap = RLDDICreateRGBMap(dwRMask,dwGMask,dwBMask);
  134. alloc = &driver->rgbmap->alloc;
  135. }
  136. cmap = RLDDICreateIndirectColormap(alloc, 32768);
  137. if (cmap == NULL || cmap->priv == NULL)
  138. return DDERR_OUTOFMEMORY;
  139. driver->pixelmap = RLDDIIndirectColormapGetMap(cmap);
  140. pCtx->pRampMap = (PUINT32)driver->pixelmap;
  141. rampmap = RLDDICreateRampmap(cmap);
  142. if (rampmap)
  143. *rampmap_return = rampmap;
  144. else
  145. return DDERR_OUTOFMEMORY;
  146. return DD_OK;
  147. }
  148. static void ReleaseRampmap(RLDDIRampmap* rampmap)
  149. {
  150. if (rampmap != NULL)
  151. {
  152. RLDDIColormap* cmap = rampmap->cmap;
  153. RLDDIDestroyRampmap(rampmap);
  154. if (cmap != NULL)
  155. cmap->destroy(cmap);
  156. }
  157. }
  158. //-----------------------------------------------------------------------------
  159. //
  160. // RLDDIRampCreate
  161. //
  162. // Creates the original RLDDIRampLightingDriver with associated lists. The
  163. // pointer returned is kept in pCtx->pRampDrv.
  164. //
  165. //-----------------------------------------------------------------------------
  166. RLDDIRampLightingDriver* RLDDIRampCreate(PD3DI_RASTCTX pCtx/*int width, int height, LPDIRECT3DDEVICEI lpD3DDevI*/)
  167. {
  168. RLDDIRampLightingDriver* driver;
  169. RLDDISoftLightingDriver* sdriver;
  170. int i;
  171. if (D3DMalloc((void**) &driver, sizeof(RLDDIRampLightingDriver)))
  172. return NULL;
  173. memset(driver, 0, sizeof(RLDDIRampLightingDriver));
  174. sdriver = (RLDDISoftLightingDriver*)driver;
  175. pCtx->pRampDrv = driver;
  176. // sdriver->driver.prev = NULL;
  177. // sdriver->driver.next = NULL;
  178. // sdriver->driver.width = width;
  179. // sdriver->driver.height = height;
  180. // sdriver->driver.destroy = Destroy;
  181. // sdriver->driver.service = RampLightingService;
  182. // sdriver->driver.lpD3DDevI = lpD3DDevI;
  183. /*
  184. * Initialise driver specific fields.
  185. */
  186. // sdriver->count = 0;
  187. // sdriver->lights = NULL;
  188. LIST_INITIALIZE(&driver->materials);
  189. LIST_INITIALIZE(&driver->orphans);
  190. CIRCLE_QUEUE_INITIALIZE(&driver->agequeue,AgeList);
  191. for (i = 0; i < AGE_MAX; i++)
  192. {
  193. LIST_INITIALIZE(&driver->agelists[i].agelist);
  194. CIRCLE_QUEUE_INSERT_END(&driver->agequeue, AgeList,
  195. &driver->agelists[i], list);
  196. }
  197. driver->active = CIRCLE_QUEUE_FIRST(&driver->agequeue);
  198. driver->already_aged = FALSE;
  199. LIST_INITIALIZE(&driver->rmactive);
  200. for (i = 0; i < HASH_SIZE; i++)
  201. LIST_INITIALIZE(&driver->hash[i]);
  202. // LIST_INITIALIZE(&driver->specular_tables);
  203. // driver->specular_table = NULL;
  204. driver->fog_enable = FALSE;
  205. driver->fog_color = FALSE;
  206. sdriver->fog_mode = D3DFOG_NONE;
  207. if (InitRampmap(pCtx, driver, &driver->rampmap) == S_OK)
  208. return /*(RLDDIDriver*)*/ driver;
  209. else
  210. return NULL;
  211. }
  212. //-----------------------------------------------------------------------------
  213. //
  214. // RLDDIRampDestroy
  215. //
  216. // Destroys a RLDDIRampLightingDriver with all associated objects and memory.
  217. // The pCtx->pRampDrv pointer should be set to NULL after this occurs.
  218. //
  219. //-----------------------------------------------------------------------------
  220. void RLDDIRampDestroy(RLDDIRampLightingDriver* drv)
  221. {
  222. // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)drv;
  223. RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv;
  224. // if (sdriver->lights) {
  225. // D3DFree(sdriver->lights);
  226. // }
  227. //
  228. // {
  229. // SpecularTable* spec;
  230. // SpecularTable* spec_next;
  231. //
  232. // for (spec = LIST_FIRST(&driver->specular_tables);
  233. // spec;
  234. // spec = spec_next) {
  235. // spec_next = LIST_NEXT(spec,list);
  236. // D3DFree(spec);
  237. // }
  238. // }
  239. //
  240. ReclaimMaterials(driver);
  241. ReleaseRampmap(driver->rampmap);
  242. RLDDIDestroyRGBMap(driver->rgbmap);
  243. // this must be done AFTER ReclaimMaterials
  244. if (driver->palette)
  245. {
  246. RLDDIDestroyPalette(driver->palette);
  247. }
  248. D3DFree(drv);
  249. }
  250. static void ReclaimMaterials(RLDDIRampLightingDriver* driver)
  251. {
  252. /*
  253. * Reclaim materials.
  254. */
  255. for (ExtMaterial* extmat = LIST_FIRST(&driver->materials);
  256. extmat;
  257. extmat = LIST_FIRST(&driver->materials))
  258. {
  259. delete extmat;
  260. }
  261. for (IntMaterial* intmat = LIST_FIRST(&driver->orphans);
  262. intmat;
  263. intmat = LIST_FIRST(&driver->orphans))
  264. {
  265. delete intmat;
  266. }
  267. /*
  268. * After destroying all the materials, there should be nothing
  269. * left in the ramp material hash tables. Lets just make sure.
  270. */
  271. for (int i = 0; i < HASH_SIZE; i++)
  272. {
  273. DDASSERT(LIST_FIRST(&driver->hash[i]) == NULL);
  274. }
  275. }
  276. ExtMaterial::ExtMaterial(RLDDIRampLightingDriver* adriver, D3DMATERIALHANDLE hMat)
  277. {
  278. D3D_INFO(7, "(Rast) Making new ExtMaterial(%08x)", this);
  279. driver = adriver;
  280. generation = 0;
  281. texture_generation = 0;
  282. texture = NULL;
  283. LIST_INITIALIZE(&intlist);
  284. }
  285. ExtMaterial::~ExtMaterial()
  286. {
  287. D3D_INFO(7, "(Rast) Destroying ExtMaterial(%08x)", this);
  288. IntMaterial* intmat;
  289. /*
  290. * Transfer active internal materials to the driver's orphans list
  291. * to be reclaimed after Clear. Free any inactive ones now.
  292. */
  293. while (LIST_FIRST(&intlist))
  294. {
  295. intmat = LIST_FIRST(&intlist);
  296. if (intmat->IsActive())
  297. {
  298. D3D_INFO(7, "(Rast) IntMaterial(%08x) is still active, moving to orphan list",
  299. intmat);
  300. intmat->Orphan();
  301. }
  302. else
  303. delete intmat;
  304. }
  305. if (driver->current_material == this)
  306. {
  307. D3D_WARN(3, "(Rast) Destroying current material, setting to NULL");
  308. driver->current_material = NULL;
  309. }
  310. }
  311. #undef DPF_MODNAME
  312. #define DPF_MODNAME "ExtMaterial::SetMaterial"
  313. void ExtMaterial::SetMaterial(D3DMATERIAL* lpMat)
  314. {
  315. D3D_INFO(7, "(Rast) Setting value of ExtMaterial(%08x)", this);
  316. if (!memcmp(&mat, lpMat, sizeof(D3DMATERIAL)))
  317. {
  318. D3D_WARN(7, "(Rast) ExtMaterial::SetMaterial: New value is identical to old value, ignoring");
  319. return;
  320. }
  321. mat = *lpMat;
  322. if (mat.hTexture)
  323. {
  324. PD3DI_SPANTEX tex;
  325. #ifdef DEBUG
  326. __try
  327. {
  328. #endif
  329. tex = HANDLE_TO_SPANTEX(mat.hTexture);
  330. texture_generation = tex->iGeneration;
  331. texture = tex;
  332. #ifdef DEBUG
  333. }
  334. __except (EXCEPTION_EXECUTE_HANDLER)
  335. {
  336. D3D_ERR("Invalid texture handle");
  337. mat.hTexture = 0;
  338. texture = NULL;
  339. }
  340. #endif
  341. }
  342. else texture = NULL;
  343. Age();
  344. }
  345. void ExtMaterial::Age()
  346. {
  347. IntMaterial* intmat;
  348. /*
  349. * Transfer active internal materials to the driver's orphans list
  350. * to be reclaimed after Clear. Free any inactive ones now.
  351. */
  352. while (LIST_FIRST(&intlist))
  353. {
  354. intmat = LIST_FIRST(&intlist);
  355. if (intmat->IsActive())
  356. {
  357. D3D_INFO(7, "(Rast) IntMaterial(%08x) is still active, moving to orphan list",
  358. intmat);
  359. intmat->Orphan();
  360. }
  361. else
  362. delete intmat;
  363. }
  364. generation++;
  365. }
  366. IntMaterial* ExtMaterial::FindIntMaterial()
  367. {
  368. IntMaterial* intmat;
  369. if (texture)
  370. {
  371. D3D_INFO(7, "(Rast) Checking texture in ExtMaterial(%08x) for new palette or texture swap", this);
  372. PD3DI_SPANTEX tex;
  373. tex = HANDLE_TO_SPANTEX(mat.hTexture);
  374. if (tex != texture)
  375. {
  376. D3D_WARN(1, "(Rast) Textures swapped, discarding old materials");
  377. texture_generation = tex->iGeneration;
  378. texture = tex;
  379. Age();
  380. }
  381. else if (texture_generation != tex->iGeneration)
  382. {
  383. D3D_WARN(1, "(Rast) Texture has changed, discarding old materials");
  384. texture_generation = tex->iGeneration;
  385. Age();
  386. }
  387. }
  388. D3D_INFO(7, "(Rast) Searching ExtMaterial(%08x) for an IntMaterial", this);
  389. for (intmat = LIST_FIRST(&intlist); intmat; intmat = LIST_NEXT(intmat,list))
  390. {
  391. if (intmat->Valid())
  392. {
  393. /*
  394. * Found it. Move to the front of the list to optimise searches.
  395. */
  396. LIST_DELETE(intmat, list);
  397. LIST_INSERT_ROOT(&intlist, intmat, list);
  398. D3D_INFO(7, "(Rast) IntMaterial(%08x) found", intmat);
  399. return intmat;
  400. }
  401. }
  402. D3D_INFO(7, "(Rast) No matching IntMaterial found, creating new one");
  403. return new IntMaterial(this);
  404. }
  405. /*
  406. * Find what range of values lighting should take. The base is the
  407. * pixel value (in fixed point) of the dark end of the material. The
  408. * shift value is user to convert a 0.16 fixed point shade into the
  409. * range needed for the material. e.g.
  410. *
  411. * pixel = base + (VALTOFX8(shade) << shift);
  412. *
  413. */
  414. HRESULT ExtMaterial::FindLightingRange(unsigned long* base,
  415. unsigned long* size,
  416. BOOL* specular,
  417. unsigned long** texture_colors)
  418. {
  419. IntMaterial* intmat;
  420. D3D_INFO(7, "(Rast) Finding color ranges for ExtMaterial(%08x)", this);
  421. intmat = FindIntMaterial();
  422. if (intmat == NULL) return DDERR_NOTFOUND;
  423. /*
  424. * Delegate to the internal material.
  425. */
  426. D3D_INFO(7, "(Rast) Using IntMaterial(%08x) for ExtMaterial(%08x)", intmat, this);
  427. return intmat->FindLightingRange(base, size, specular, texture_colors);
  428. }
  429. IntMaterial::IntMaterial(ExtMaterial* anextmat)
  430. {
  431. D3D_INFO(7, "(Rast) Creating new IntMaterial(%08x) for ExtMaterial(%08x)",
  432. this, extmat);
  433. /*
  434. * Remember the driver object.
  435. */
  436. extmat = anextmat;
  437. driver = extmat->driver;
  438. RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*) driver;
  439. /*
  440. * Initialise stuff so that if we have to abort, the destructor can
  441. * clean up.
  442. */
  443. active = FALSE;
  444. ramps = NULL;
  445. colors = NULL;
  446. ambient = sdriver->ambient;
  447. viewport_id = driver->viewport_id;
  448. fog_enable = driver->fog_enable;
  449. fog_color = driver->fog_color;
  450. generation = extmat->generation;
  451. /*
  452. * Put us on the list of internal materials owned by our creator.
  453. */
  454. LIST_INSERT_ROOT(&extmat->intlist, this, list);
  455. /*
  456. * Add to the age=1 list for material use tracking.
  457. */
  458. AgeList* age1 = CIRCLE_QUEUE_NEXT(&driver->agequeue,driver->active,list);
  459. age = age1;
  460. LIST_INSERT_ROOT(&age1->agelist, this, agelist);
  461. /*
  462. * Record the current external material's D3DMATERIAL. Note that this
  463. * can change at any time. We need a snapshot.
  464. */
  465. mat = extmat->mat;
  466. PD3DI_SPANTEX tex;
  467. if (mat.hTexture)
  468. tex = HANDLE_TO_SPANTEX(mat.hTexture);
  469. else
  470. tex = NULL;
  471. if (tex == NULL)
  472. ramp_count = 1;
  473. else
  474. ramp_count = tex->iPaletteSize;
  475. ramps = new RampMaterial*[ramp_count];
  476. if (ramps == NULL)
  477. {
  478. D3D_ERR("Out of memory creating IntMaterial");
  479. delete this;
  480. //this = NULL;
  481. return;
  482. }
  483. colors = new unsigned long[ramp_count];
  484. memset(ramps, 0, ramp_count * sizeof(RampMaterial*));
  485. D3DMATERIAL tmat;
  486. tmat = mat;
  487. tmat.hTexture = 0L;
  488. LPPALETTEENTRY palette = NULL;
  489. if (tex)
  490. palette = (LPPALETTEENTRY)tex->pPalette;
  491. for (int i = 0; i < ramp_count; i++)
  492. {
  493. if (tex)
  494. {
  495. tmat.ambient.r = (float)((palette->peRed * mat.ambient.r) / 255.0);
  496. tmat.ambient.g = (float)((palette->peGreen * mat.ambient.g) / 255.0);
  497. tmat.ambient.b = (float)((palette->peBlue * mat.ambient.b) / 255.0);
  498. tmat.ambient.a = mat.ambient.a;
  499. tmat.diffuse.r = (float)((palette->peRed * mat.diffuse.r) / 255.0);
  500. tmat.diffuse.g = (float)((palette->peGreen * mat.diffuse.g) / 255.0);
  501. tmat.diffuse.b = (float)((palette->peBlue * mat.diffuse.b) / 255.0);
  502. tmat.diffuse.a = mat.diffuse.a;
  503. palette++;
  504. }
  505. ramps[i] = RampMaterial::Find(driver, &tmat);
  506. if (ramps[i] == NULL)
  507. {
  508. D3D_ERR("Can't find RampMaterial for IntMaterial");
  509. delete this;
  510. //this = NULL;
  511. return;
  512. }
  513. }
  514. }
  515. IntMaterial::~IntMaterial()
  516. {
  517. D3D_INFO(9, "(Rast) Destroying IntMaterial(%08x)", this);
  518. /*
  519. * Give up our colors.
  520. */
  521. if (active) Deactivate();
  522. /*
  523. * Remove from lists.
  524. */
  525. LIST_DELETE(this, list);
  526. LIST_DELETE(this, agelist);
  527. /*
  528. * Release underlying ramp materials and memory.
  529. */
  530. if (ramps)
  531. {
  532. for (int i = 0; i < ramp_count; i++)
  533. if (ramps[i])
  534. ramps[i]->Release();
  535. delete ramps;
  536. }
  537. if (colors)
  538. delete colors;
  539. }
  540. int IntMaterial::Valid()
  541. {
  542. RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*) driver;
  543. /*
  544. * Ambient only matters for lit materials.
  545. */
  546. if (mat.dwRampSize > 1 && ambient != sdriver->ambient)
  547. return FALSE;
  548. return (viewport_id == driver->viewport_id
  549. && fog_enable == driver->fog_enable
  550. && fog_color == driver->fog_color
  551. && generation == extmat->generation);
  552. }
  553. HRESULT IntMaterial::FindLightingRange(unsigned long* base,
  554. unsigned long* size,
  555. BOOL* specular,
  556. unsigned long** texture_colors)
  557. {
  558. HRESULT error;
  559. D3D_INFO(7, "(Rast) Finding color ranges for IntMaterial(%08x)", this);
  560. /*
  561. * Make sure the material is active.
  562. */
  563. if ((error = Activate()) != DD_OK)
  564. {
  565. D3D_ERR("Can't activate IntMaterial");
  566. return error;
  567. }
  568. /*
  569. * For non-textured materials, the base is the start of the
  570. * color range. For textured materials, the base is zero and
  571. * texture_colors is set to the array containing the color bases.
  572. */
  573. if (mat.hTexture)
  574. {
  575. // until we find a reason to do otherwise, have base
  576. // be just a plain color index offset (no alpha, and no shift
  577. // up by 8
  578. // *base = CI_MAKE((int)(mat.diffuse.a * 255.0), 0, 0);
  579. *base = 0;
  580. *texture_colors = colors;
  581. }
  582. else
  583. {
  584. // *base = CI_MAKE((int)(mat.diffuse.a * 255.0), colors[0], 0);
  585. *base = colors[0];
  586. }
  587. *size = mat.dwRampSize;
  588. // same code as in SetColorsStd and SetColorsFog
  589. if ((*size <= 2) || ((mat.specular.r == 0.0) &&
  590. (mat.specular.g == 0.0) &&
  591. (mat.specular.b == 0.0)))
  592. *specular = FALSE;
  593. else
  594. *specular = TRUE;
  595. return DD_OK;
  596. }
  597. HRESULT IntMaterial::Activate()
  598. {
  599. HRESULT error;
  600. /*
  601. * If we are already active, just make sure we are on the right list.
  602. */
  603. if (active)
  604. {
  605. D3D_INFO(7, "(Rast) IntMaterial(%08x) is already active", this);
  606. if (age != driver->active)
  607. {
  608. D3D_INFO(7, "(Rast) Moving IntMaterial(%08x) to list %08x",
  609. this, driver->active);
  610. LIST_DELETE(this, agelist);
  611. LIST_INSERT_ROOT(&driver->active->agelist, this, agelist);
  612. age = driver->active;
  613. }
  614. else
  615. {
  616. D3D_INFO(7, "(Rast) IntMaterial(%08x) is already on the active list", this);
  617. }
  618. return DD_OK;
  619. }
  620. D3D_INFO(6, "(Rast) Activating IntMaterial(%08x)", this);
  621. /*
  622. * Activate all the underlying materials and record their bases.
  623. */
  624. for (int i = 0; i < ramp_count; i++)
  625. {
  626. if ((error = ramps[i]->Activate()) != DD_OK)
  627. {
  628. D3D_WARN(0, "Failed to activate RampMaterial(%08x) for IntMaterial(%08x)",
  629. ramps[i], this);
  630. /*
  631. * Failed to activate all the underlying RampMaterials.
  632. * Deactivate any which we did manage.
  633. */
  634. for (int j = 0; j < i; j++)
  635. ramps[j]->Deactivate();
  636. return error;
  637. }
  638. colors[i] = ramps[i]->Base();
  639. }
  640. /*
  641. * We are now active, so remember and put us on the age=0 list.
  642. */
  643. D3D_INFO(7, "(Rast) Moving IntMaterial(%08x) to list %08x", this, driver->active);
  644. active = TRUE;
  645. LIST_DELETE(this, agelist);
  646. LIST_INSERT_ROOT(&driver->active->agelist, this, agelist);
  647. age = driver->active;
  648. return DD_OK;
  649. }
  650. void IntMaterial::Deactivate()
  651. {
  652. if (!active) return;
  653. D3D_INFO(6, "(Rast) Deactivating IntMaterial(%08x)", this);
  654. for (int i = 0; i < ramp_count; i++)
  655. ramps[i]->Deactivate();
  656. active = FALSE;
  657. }
  658. void IntMaterial::Orphan()
  659. {
  660. LIST_DELETE(this, list);
  661. LIST_INSERT_ROOT(&driver->orphans, this, list);
  662. }
  663. RampMaterial::RampMaterial(RLDDIRampLightingDriver* adriver,
  664. D3DMATERIAL* lpMat,
  665. float anambient)
  666. : driver(adriver)
  667. {
  668. D3D_INFO(6, "(Rast) Creating new RampMaterial(%08x) color=[%d,%d,%d] size=%d",
  669. this,
  670. (int)(255 * lpMat->diffuse.r),
  671. (int)(255 * lpMat->diffuse.g),
  672. (int)(255 * lpMat->diffuse.b),
  673. lpMat->dwRampSize);
  674. unsigned int hash = CVAL_TO_RGBA(&lpMat->diffuse) % HASH_SIZE; /* XXX */
  675. LIST_INSERT_ROOT(&driver->hash[hash], this, hash);
  676. LIST_INITIALIZE(&sharers);
  677. usage = 1;
  678. active = 0;
  679. ramp = NULL;
  680. owner = FALSE;
  681. ambient = anambient;
  682. mat = *lpMat;
  683. fog_enable = driver->fog_enable;
  684. fog_color = driver->fog_color;
  685. LIST_INITIALIZE_MEMBER(this,deferredlist);
  686. }
  687. RampMaterial::~RampMaterial()
  688. {
  689. D3D_INFO(9, "(Rast) Destroying RampMaterial(%08x)", this);
  690. DDASSERT(usage == 0); // don't destroy stuff, call Release
  691. DDASSERT(active == 0); // don't Release an active material
  692. LIST_DELETE(this, hash);
  693. }
  694. int RampMaterial::MaterialSame(D3DMATERIAL* mat1, D3DMATERIAL* mat2)
  695. {
  696. if (mat1->ambient.r == mat2->ambient.r
  697. && mat1->ambient.g == mat2->ambient.g
  698. && mat1->ambient.b == mat2->ambient.b
  699. && mat1->diffuse.r == mat2->diffuse.r
  700. && mat1->diffuse.g == mat2->diffuse.g
  701. && mat1->diffuse.b == mat2->diffuse.b
  702. && mat1->specular.r == mat2->specular.r
  703. && mat1->specular.g == mat2->specular.g
  704. && mat1->specular.b == mat2->specular.b
  705. && mat1->emissive.r == mat2->emissive.r
  706. && mat1->emissive.g == mat2->emissive.g
  707. && mat1->emissive.b == mat2->emissive.b
  708. && mat1->power == mat2->power
  709. && mat1->dwRampSize == mat2->dwRampSize)
  710. return 1;
  711. return 0;
  712. }
  713. #define ABS(a) ((a) > 0 ? (a) : -(a))
  714. int RampMaterial::RGBDist(D3DCOLORVALUE* rgb1, D3DCOLORVALUE* rgb2)
  715. {
  716. return ABS((int)(255.0 * (rgb1->r - rgb2->r)))
  717. + ABS((int)(255.0 * (rgb1->g - rgb2->g)))
  718. + ABS((int)(255.0 * (rgb1->b - rgb2->b)));
  719. }
  720. int RampMaterial::CompareMaterials(D3DMATERIAL* mat1, D3DMATERIAL* mat2)
  721. {
  722. return (RGBDist(&mat1->ambient, &mat2->ambient)
  723. + RGBDist(&mat1->diffuse, &mat2->diffuse)
  724. + RGBDist(&mat1->specular, &mat2->specular)
  725. + ABS((int)mat1->power - (int)mat2->power));
  726. }
  727. RampMaterial* RampMaterial::Find(RLDDIRampLightingDriver* driver,
  728. D3DMATERIAL* mat)
  729. {
  730. D3D_INFO(8, "(Rast) Searching for RampMaterial");
  731. unsigned int hash = CVAL_TO_RGBA(&mat->diffuse) % HASH_SIZE; /* XXX */
  732. RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)driver;
  733. RampMaterial* rm = NULL;
  734. float ambient;
  735. if (mat->dwRampSize > 1 && !driver->fog_enable)
  736. ambient = sdriver->ambient;
  737. else
  738. ambient = 0.0f;
  739. for (rm = LIST_FIRST(&driver->hash[hash]);
  740. rm; rm = LIST_NEXT(rm,hash))
  741. {
  742. if (MaterialSame(&rm->mat, mat)
  743. && rm->ambient == ambient
  744. && driver->fog_enable == rm->fog_enable
  745. && driver->fog_color == rm->fog_color)
  746. break;
  747. }
  748. if (rm)
  749. {
  750. rm->usage++;
  751. D3D_INFO(7, "(Rast) RampMaterial(%08x) found, usage is now %d",
  752. rm, rm->usage);
  753. return rm;
  754. }
  755. else
  756. {
  757. D3D_INFO(7, "(Rast) No matching material found, creating new one");
  758. return new RampMaterial(driver, mat, ambient);
  759. }
  760. }
  761. void RampMaterial::Release()
  762. {
  763. usage--;
  764. D3D_INFO(7, "(Rast) Releasing RampMaterial(%08x), usage is now %d", this, usage);
  765. if (usage == 0)
  766. delete this;
  767. }
  768. HRESULT RampMaterial::Activate()
  769. {
  770. HRESULT error;
  771. D3D_INFO(6, "(Rast) Activating RampMaterial(%08x)", this);
  772. /*
  773. * The first time we are activated, allocate some colors.
  774. */
  775. if (active == 0)
  776. {
  777. if ((error = AllocateColors()) != DD_OK)
  778. return error;
  779. }
  780. active++;
  781. DDASSERT(active <= usage);
  782. return DD_OK;
  783. }
  784. void RampMaterial::Deactivate()
  785. {
  786. D3D_INFO(6, "(Rast) Deactivating RampMaterial(%08x)", this);
  787. active--;
  788. DDASSERT(active >= 0);
  789. /*
  790. * Free our colors if none of our users are active.
  791. */
  792. if (active == 0)
  793. FreeColors();
  794. }
  795. unsigned long RampMaterial::Base()
  796. {
  797. DDASSERT(ramp != NULL);
  798. D3D_INFO(7, "(Rast) Base pixel for RampMaterial(%08x) is %d", this, ramp->base);
  799. return ramp->base;
  800. }
  801. HRESULT RampMaterial::AllocateColors()
  802. {
  803. D3D_INFO(6, "(Rast) Allocating colors for RampMaterial(%08x)", this);
  804. DDASSERT(ramp == NULL);
  805. ramp = RLDDIRampmapAllocate(driver->rampmap, mat.dwRampSize);
  806. if (ramp)
  807. {
  808. D3D_INFO(7, "(Rast) Ramp(%08x) range %d..%d allocated for RampMaterial(%08x)",
  809. ramp, ramp->base, ramp->base + ramp->size - 1, this);
  810. /*
  811. * We got a ramp, so mark this material as owning the ramp and add
  812. * it to the active list.
  813. */
  814. owner = TRUE;
  815. SetColors();
  816. /*
  817. * This material now owns the ramp, so place it on the active list.
  818. */
  819. D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to active material list", this);
  820. LIST_INSERT_ROOT(&driver->rmactive, this, list);
  821. /*
  822. * No sharers yet.
  823. */
  824. LIST_INITIALIZE(&sharers);
  825. }
  826. else
  827. {
  828. D3D_INFO(7, "(Rast) No Ramp allocated, searching for closest active material");
  829. /*
  830. * Search the active list for a similar material and share its ramp.
  831. */
  832. RampMaterial *t;
  833. RampMaterial *best;
  834. int closeness, c;
  835. best = NULL;
  836. closeness = INT_MAX;
  837. do
  838. {
  839. for (t = LIST_FIRST(&driver->rmactive); t; t = LIST_NEXT(t,list))
  840. {
  841. if (t->ramp)
  842. {
  843. if (mat.dwRampSize != t->mat.dwRampSize)
  844. continue;
  845. c = CompareMaterials(&mat, &t->mat);
  846. if (c < closeness)
  847. {
  848. best = t;
  849. closeness = c;
  850. }
  851. }
  852. }
  853. if (best == NULL)
  854. {
  855. t = LIST_FIRST(&driver->rmactive);
  856. mat.dwRampSize = t->mat.dwRampSize;
  857. D3D_WARN(2, "(Rast) No matching ramp found in palette");
  858. D3D_WARN(2, "(Rast) Changing material rampsize to match first list entry");
  859. }
  860. } while (!best);
  861. DDASSERT(best != NULL);
  862. /*
  863. * Add the material to the list of sharers for the ramp owner. If
  864. * the owner later stops using the ramp, it will be inherited by the
  865. * first material on the sharers list.
  866. */
  867. D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) as sharer of RampMaterial(%08x)",
  868. this, best);
  869. LIST_INSERT_ROOT(&best->sharers, this, list);
  870. ramp = best->ramp;
  871. owner = FALSE;
  872. }
  873. return DD_OK;
  874. }
  875. void RampMaterial::FreeColors()
  876. {
  877. D3D_INFO(6, "(Rast) Freeing colors for RampMaterial(%08x)", this);
  878. DDASSERT(ramp != NULL);
  879. /*
  880. * First remove us from either rmactive or owner->sharers depending on
  881. * whether we are sharing a ramp.
  882. */
  883. LIST_DELETE(this, list);
  884. /*
  885. * If we were waiting for a deferred call to SetColors, make sure
  886. * it doesn't happen.
  887. */
  888. if (!LIST_ORPHAN_MEMBER(this,deferredlist))
  889. {
  890. D3D_INFO(7, "(Rast) Removing RampMaterial(%08x) from deferred SetColor list",
  891. this);
  892. LIST_DELETE(this, deferredlist);
  893. }
  894. /*
  895. * If we owned the ramp, then either donate it to a sharer or free it
  896. * as appropriate.
  897. */
  898. if (owner)
  899. {
  900. D3D_INFO(7, "(Rast) RampMaterial(%08x) owned Ramp(%08x)", this, ramp);
  901. if (LIST_FIRST(&sharers))
  902. {
  903. /*
  904. * There were sharers, so donate the ramp to the first one and
  905. * make the others sharers of the new owner.
  906. */
  907. RampMaterial* new_owner = LIST_FIRST(&sharers);
  908. RampMaterial* t;
  909. RampMaterial* tnext;
  910. D3D_INFO(7, "(Rast) New owner of Ramp(%08x) is RampMaterial(%08x)",
  911. ramp, new_owner);
  912. new_owner->owner = TRUE;
  913. /*
  914. * Defer setting the colours until the next frame to avoid
  915. * palette flashing. Check to see if it is already there.
  916. */
  917. if (LIST_ORPHAN_MEMBER(new_owner,deferredlist))
  918. {
  919. D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to deferred SetColor list",
  920. this);
  921. LIST_INSERT_ROOT(&driver->rmdeferred, new_owner, deferredlist);
  922. }
  923. /*
  924. * Remove from the sharers list and add to the active list.
  925. * Clear the new owner's sharers list so that we can add
  926. * the rest of the old sharers to it.
  927. */
  928. D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to active material list",
  929. new_owner);
  930. LIST_DELETE(new_owner, list);
  931. LIST_INSERT_ROOT(&driver->rmactive, new_owner, list);
  932. LIST_INITIALIZE(&new_owner->sharers);
  933. /*
  934. * Traverse the rest of the sharers, and add them as
  935. * sharers of the new owner if they are still using the
  936. * ramp, otherwise add them to the inactive list.
  937. */
  938. for (t = LIST_FIRST(&sharers); t; t = tnext)
  939. {
  940. tnext = LIST_NEXT(t,list);
  941. D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) as sharer of RampMaterial(%08x)",
  942. t, new_owner);
  943. LIST_INSERT_ROOT(&new_owner->sharers, t, list);
  944. }
  945. }
  946. else
  947. {
  948. D3D_INFO(7, "(Rast) Freeing Ramp(%08x) for RampMaterial(%08x)", ramp, this);
  949. /*
  950. * XXX maybe we should donate the ramp to a material
  951. * which is sharing the ramp of a material which does not
  952. * match its own colors.
  953. *
  954. * Set the contents of the ramp to black, which will
  955. * possibly help out some lower level color allocation.
  956. */
  957. int i;
  958. RLDDIColormap* cmap = driver->rampmap->cmap;
  959. for (i = 0; i < ramp->size; i++)
  960. cmap->set_color(cmap, ramp->base + i,
  961. 0, 0, 0);
  962. RLDDIRampmapFree(driver->rampmap, ramp);
  963. }
  964. }
  965. ramp = NULL;
  966. }
  967. void RampMaterial::SetColorsStd()
  968. {
  969. int base = ramp->base;
  970. int size = ramp->size;
  971. int dsize;
  972. int ssize;
  973. int i, specular;
  974. float ambient = (float) VALTOD(this->ambient);
  975. RLDDIColormap* cmap = driver->rampmap->cmap;
  976. if ((size <= 2) || ((mat.specular.r == 0.0) &&
  977. (mat.specular.g == 0.0) &&
  978. (mat.specular.b == 0.0)))
  979. specular = FALSE;
  980. else
  981. specular = TRUE;
  982. if (ramp->size == 1)
  983. {
  984. cmap->set_color(cmap, base, (int)(255.0 * mat.diffuse.r),
  985. (int)(255.0 * mat.diffuse.g),
  986. (int)(255.0 * mat.diffuse.b));
  987. return;
  988. }
  989. if (specular != 0)
  990. {
  991. dsize = (3 * ramp->size) / 4;
  992. ssize = ramp->size / 4;
  993. }
  994. else
  995. {
  996. dsize = ramp->size;
  997. ssize = 0;
  998. }
  999. for (i = 0; i < dsize; i++)
  1000. {
  1001. float intensity = (1 - ambient) * ((float)i / (dsize - 1));
  1002. float r = (mat.emissive.r
  1003. + ambient * mat.ambient.r
  1004. + intensity * mat.diffuse.r);
  1005. float g = (mat.emissive.g
  1006. + ambient * mat.ambient.g
  1007. + intensity * mat.diffuse.g);
  1008. float b = (mat.emissive.b
  1009. + ambient * mat.ambient.b
  1010. + intensity * mat.diffuse.b);
  1011. if (r > 1.0) r = (float)1.0;
  1012. if (g > 1.0) g = (float)1.0;
  1013. if (b > 1.0) b = (float)1.0;
  1014. cmap->set_color(cmap, base + i, (int)(255.0 * r),
  1015. (int)(255.0 * g),
  1016. (int)(255.0 * b));
  1017. }
  1018. if (ssize)
  1019. {
  1020. float mdr, mdg, mdb; /* Maximum diffuse values */
  1021. float sr, sg, sb;
  1022. mdr = (mat.emissive.r
  1023. + ambient * mat.ambient.r
  1024. + (1 - ambient) * mat.diffuse.r);
  1025. mdg = (mat.emissive.g
  1026. + ambient * mat.ambient.g
  1027. + (1 - ambient) * mat.diffuse.g);
  1028. mdb = (mat.emissive.b
  1029. + ambient * mat.ambient.b
  1030. + (1 - ambient) * mat.diffuse.b);
  1031. if (mdr > 1.0) mdr = (float)1.0;
  1032. if (mdg > 1.0) mdg = (float)1.0;
  1033. if (mdb > 1.0) mdb = (float)1.0;
  1034. sr = mdr + mat.specular.r;
  1035. sg = mdg + mat.specular.g;
  1036. sb = mdb + mat.specular.b;
  1037. if (sr > 1.0) sr = (float)1.0;
  1038. if (sg > 1.0) sg = (float)1.0;
  1039. if (sb > 1.0) sb = (float)1.0;
  1040. for (i = 0; i < ssize; i++)
  1041. {
  1042. float s = (float)i / (ssize - 1);
  1043. float r = (1 - s) * mdr + s * sr;
  1044. float g = (1 - s) * mdg + s * sg;
  1045. float b = (1 - s) * mdb + s * sb;
  1046. cmap->set_color(cmap,
  1047. base + dsize + i,
  1048. (int)(255.0 * r),
  1049. (int)(255.0 * g),
  1050. (int)(255.0 * b));
  1051. }
  1052. }
  1053. }
  1054. void RampMaterial::SetColorsFog()
  1055. {
  1056. int base = ramp->base;
  1057. int size = ramp->size;
  1058. int dsize;
  1059. int ssize;
  1060. int i, specular;
  1061. float ambient = (float) VALTOD(this->ambient);
  1062. RLDDIColormap* cmap = driver->rampmap->cmap;
  1063. float fr, fg, fb;
  1064. fr = RGBA_GETRED(driver->fog_color) / 255.0f;
  1065. fg = RGBA_GETGREEN(driver->fog_color) / 255.0f;
  1066. fb = RGBA_GETBLUE(driver->fog_color) / 255.0f;
  1067. if ((size <= 2) || ((mat.specular.r == 0.0) &&
  1068. (mat.specular.g == 0.0) &&
  1069. (mat.specular.b == 0.0)))
  1070. specular = 0;
  1071. if (ramp->size == 1)
  1072. {
  1073. cmap->set_color(cmap, base, (int)(255.0 * mat.diffuse.r),
  1074. (int)(255.0 * mat.diffuse.g),
  1075. (int)(255.0 * mat.diffuse.b));
  1076. return;
  1077. }
  1078. if (specular != 0)
  1079. {
  1080. dsize = (3 * ramp->size) / 4;
  1081. ssize = ramp->size / 4;
  1082. }
  1083. else
  1084. {
  1085. dsize = ramp->size;
  1086. ssize = 0;
  1087. }
  1088. for (i = 0; i < dsize; i++)
  1089. {
  1090. float intensity = (1 - ambient) * ((float)i / (dsize - 1));
  1091. float r = (mat.emissive.r
  1092. + ambient * mat.ambient.r
  1093. + intensity * mat.diffuse.r);
  1094. float g = (mat.emissive.g
  1095. + ambient * mat.ambient.g
  1096. + intensity * mat.diffuse.g);
  1097. float b = (mat.emissive.b
  1098. + ambient * mat.ambient.b
  1099. + intensity * mat.diffuse.b);
  1100. r += (1.0f - intensity) * fr;
  1101. g += (1.0f - intensity) * fg;
  1102. b += (1.0f - intensity) * fb;
  1103. if (r > 1.0) r = (float)1.0;
  1104. if (g > 1.0) g = (float)1.0;
  1105. if (b > 1.0) b = (float)1.0;
  1106. cmap->set_color(cmap, base + i, (int)(255.0 * r),
  1107. (int)(255.0 * g),
  1108. (int)(255.0 * b));
  1109. }
  1110. if (ssize)
  1111. {
  1112. float mdr, mdg, mdb; /* Maximum diffuse values */
  1113. float sr, sg, sb;
  1114. mdr = (mat.emissive.r
  1115. + ambient * mat.ambient.r
  1116. + (1 - ambient) * mat.diffuse.r);
  1117. mdg = (mat.emissive.g
  1118. + ambient * mat.ambient.g
  1119. + (1 - ambient) * mat.diffuse.g);
  1120. mdb = (mat.emissive.b
  1121. + ambient * mat.ambient.b
  1122. + (1 - ambient) * mat.diffuse.b);
  1123. if (mdr > 1.0) mdr = (float)1.0;
  1124. if (mdg > 1.0) mdg = (float)1.0;
  1125. if (mdb > 1.0) mdb = (float)1.0;
  1126. sr = mdr + mat.specular.r;
  1127. sg = mdg + mat.specular.g;
  1128. sb = mdb + mat.specular.b;
  1129. if (sr > 1.0) sr = (float)1.0;
  1130. if (sg > 1.0) sg = (float)1.0;
  1131. if (sb > 1.0) sb = (float)1.0;
  1132. for (i = 0; i < ssize; i++)
  1133. {
  1134. float s = (float)i / (ssize - 1);
  1135. float r = (1 - s) * mdr + s * sr;
  1136. float g = (1 - s) * mdg + s * sg;
  1137. float b = (1 - s) * mdb + s * sb;
  1138. cmap->set_color(cmap,
  1139. base + dsize + i,
  1140. (int)(255.0 * r),
  1141. (int)(255.0 * g),
  1142. (int)(255.0 * b));
  1143. }
  1144. }
  1145. }
  1146. void RampMaterial::SetColors()
  1147. {
  1148. if (!LIST_ORPHAN_MEMBER(this, deferredlist))
  1149. {
  1150. LIST_DELETE(this, deferredlist);
  1151. }
  1152. D3D_INFO(7, "(Rast) Setting colors for RampMaterial(%08x)", this);
  1153. if (fog_enable)
  1154. SetColorsFog();
  1155. else
  1156. SetColorsStd();
  1157. }
  1158. //-----------------------------------------------------------------------------
  1159. //
  1160. // RLDDIRampBeginSceneHook
  1161. //
  1162. // Called at clear time to advance material ages and process deferred color
  1163. // setting. Also deletes orphaned IntMaterials.
  1164. //
  1165. //-----------------------------------------------------------------------------
  1166. void RLDDIRampBeginSceneHook(RLDDIRampLightingDriver* driver)
  1167. {
  1168. AgeList* oldest;
  1169. if (driver->already_aged)
  1170. return;
  1171. driver->already_aged = TRUE;
  1172. D3D_INFO(6, "(Rast) Aging materials in Clear");
  1173. /*
  1174. * remove the oldest list and make that the new age=0 list.
  1175. */
  1176. oldest = CIRCLE_QUEUE_LAST(&driver->agequeue);
  1177. DDASSERT(LIST_FIRST(&oldest->agelist) == NULL);
  1178. CIRCLE_QUEUE_DELETE(&driver->agequeue, oldest, list);
  1179. CIRCLE_QUEUE_INSERT_ROOT(&driver->agequeue, AgeList, oldest, list);
  1180. driver->active = oldest;
  1181. D3D_INFO(7, "(Rast) New active list is %08x", driver->active);
  1182. /*
  1183. * Set the colors of any ramp materials which inherited color
  1184. * resources last frame.
  1185. */
  1186. for (RampMaterial* rm = LIST_FIRST(&driver->rmdeferred);
  1187. rm; rm = LIST_FIRST(&driver->rmdeferred))
  1188. {
  1189. D3D_INFO(6, "(Rast) Processing deferred SetColor for RampMaterial(%08x)", rm);
  1190. rm->SetColors();
  1191. }
  1192. /*
  1193. * Any internal materials on the orphans list lost their parents last
  1194. * frame. If they are inactive, reclaim them here instead of waiting
  1195. * for them to die of old age.
  1196. */
  1197. IntMaterial* intmat;
  1198. IntMaterial* intmat_next;
  1199. for (intmat = LIST_FIRST(&driver->orphans);
  1200. intmat;
  1201. intmat = intmat_next)
  1202. {
  1203. intmat_next = LIST_NEXT(intmat,list);
  1204. if (!intmat->IsActive())
  1205. {
  1206. D3D_INFO(9, "(Rast) Destroying inactive orphan IntMaterial(%08x)", intmat);
  1207. delete intmat;
  1208. }
  1209. }
  1210. }
  1211. //-----------------------------------------------------------------------------
  1212. //
  1213. // RLDDIRampEndSceneHook
  1214. //
  1215. // Called at update time to reclaim unused color resources and reclaim
  1216. // memory for old IntMaterials.
  1217. //
  1218. // The age1 list will contain materials which were active last frame
  1219. // and have not been used since the last Clear.
  1220. // We remove their colour resources.
  1221. //
  1222. // The agemax list will contain inactive materials which have not
  1223. // been used for AGE_MAX-1 frames. These are obsolete and we reclaim
  1224. // their memory.
  1225. //
  1226. // NOT CALLING THIS CONSTITUTES A MEMORY LEAK.
  1227. //
  1228. //-----------------------------------------------------------------------------
  1229. void RLDDIRampEndSceneHook(RLDDIRampLightingDriver* driver)
  1230. {
  1231. AgeList* age1 = CIRCLE_QUEUE_NEXT(&driver->agequeue,driver->active,list);
  1232. AgeList* agemax = CIRCLE_QUEUE_LAST(&driver->agequeue);
  1233. IntMaterial* intmat;
  1234. driver->already_aged = FALSE;
  1235. D3D_INFO(9, "(Rast) Processing materials in Update");
  1236. /*
  1237. * The age1 list will contain materials which were active last frame
  1238. * and have not been used since the last Clear.
  1239. * We remove their colour resources.
  1240. */
  1241. D3D_INFO(7, "(Rast) Deactivating any materials on old active list %08x", age1);
  1242. for (intmat = LIST_FIRST(&age1->agelist);
  1243. intmat;
  1244. intmat = LIST_NEXT(intmat,agelist))
  1245. {
  1246. D3D_INFO(6, "(Rast) IntMaterial(%08x) not used this frame, deactivating", intmat);
  1247. intmat->Deactivate();
  1248. }
  1249. /*
  1250. * The agemax list will contain inactive materials which have not
  1251. * been used for AGE_MAX-1 frames. These are obsolete and we reclaim
  1252. * their memory.
  1253. */
  1254. for (intmat = LIST_FIRST(&agemax->agelist);
  1255. intmat;
  1256. // this seems wierd, but I think it is O.K. since IntMaterial's destructor
  1257. // removes itself from the agelist
  1258. intmat = LIST_FIRST(&agemax->agelist))
  1259. {
  1260. D3D_INFO(6, "(Rast) IntMaterial(%08x) dying of old age", intmat);
  1261. delete intmat;
  1262. }
  1263. }
  1264. inline ExtMaterial* MaterialHandleLookup(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
  1265. {
  1266. DDASSERT(hMat);
  1267. return (ExtMaterial*)((((D3DFE_MATERIAL*)ULongToPtr(hMat))->pRmMat));
  1268. }
  1269. //-----------------------------------------------------------------------------
  1270. //
  1271. // RLDDIRampMaterialChanged
  1272. //
  1273. // Called when the contents of D3DMATERIAL we have already made a ExtMaterial
  1274. // for changes.
  1275. //
  1276. //-----------------------------------------------------------------------------
  1277. long RLDDIRampMaterialChanged(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
  1278. {
  1279. D3DMATERIAL* lpMat = &((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat;
  1280. ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
  1281. // Don't know if MaterialChanged is supposed to unconditionally set the current
  1282. // material or not. In any case, this code seems to make the uvis RM test app
  1283. // work
  1284. if (NULL == driver->current_material)
  1285. {
  1286. driver->current_material = extmat;
  1287. }
  1288. extmat->SetMaterial(lpMat);
  1289. return DD_OK;
  1290. }
  1291. //-----------------------------------------------------------------------------
  1292. //
  1293. // RLDDIRampSetMaterial
  1294. //
  1295. // Called when a D3DLIGHTSTATE_MATERIAL changes, which sets the
  1296. // driver->current_material.
  1297. //
  1298. //-----------------------------------------------------------------------------
  1299. long RLDDIRampSetMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
  1300. {
  1301. if (hMat == NULL)
  1302. { // NULL material is legal
  1303. driver->current_material = NULL;
  1304. return D3D_OK;
  1305. }
  1306. ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
  1307. driver->current_material = extmat;
  1308. // D3DMATERIALHANDLE hMat = (D3DMATERIALHANDLE)arg;
  1309. // ExtMaterial* extmat;
  1310. // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*)drv;
  1311. // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)drv;
  1312. // LPRLDDIGENRASDRIVER rasDrv = (LPRLDDIGENRASDRIVER)drv->next;
  1313. //
  1314. // if (!extmat) {
  1315. // return DDERR_NOTFOUND;
  1316. // }
  1317. //
  1318. // if (extmat->GetMaterial()->power > 0) {
  1319. // SpecularTable* spec;
  1320. //
  1321. // for (spec = LIST_FIRST(&driver->specular_tables)
  1322. // ; // intentionally left blank
  1323. // spec;
  1324. // spec = LIST_NEXT(spec,list)) {
  1325. // if (spec->power == extmat->GetMaterial()->power)
  1326. // break;
  1327. // }
  1328. // if (spec == NULL) {
  1329. // spec = CreateSpecularTable(extmat->GetMaterial()->power);
  1330. // if (spec == NULL)
  1331. // return DDERR_OUTOFMEMORY;
  1332. // LIST_INSERT_ROOT(&driver->specular_tables, spec, list);
  1333. // }
  1334. // driver->specular_table = spec;
  1335. // } else {
  1336. // driver->specular_table = NULL;
  1337. // }
  1338. //
  1339. // sdriver->hMat = hMat;
  1340. //
  1341. // if (rasDrv->driver.lpD3DDevI->rstates[D3DRENDERSTATE_TEXTUREHANDLE] != extmat->GetMaterial()->hTexture)
  1342. // rasDrv->badRampTex = 1; /* Currently hTex are not matched */
  1343. // else
  1344. // rasDrv->badRampTex = 0;
  1345. return DD_OK;
  1346. }
  1347. //-----------------------------------------------------------------------------
  1348. //
  1349. // RLDDIRampCreateMaterial
  1350. //
  1351. // Called to create a new ExtMaterial for a given D3DFE_MATERIAL.
  1352. //
  1353. //-----------------------------------------------------------------------------
  1354. long RLDDIRampCreateMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat, PD3DI_RASTCTX pCtx)
  1355. {
  1356. D3DMATERIAL* lpMat = &((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat;
  1357. ExtMaterial* extmat;
  1358. driver->fog_enable = pCtx->pdwRenderState[D3DRENDERSTATE_FOGENABLE];
  1359. driver->fog_color = pCtx->pdwRenderState[D3DRENDERSTATE_FOGCOLOR];
  1360. extmat = new ExtMaterial(driver, hMat);
  1361. if (extmat == NULL)
  1362. return (long) NULL;
  1363. LIST_INSERT_ROOT(&driver->materials, extmat, list);
  1364. extmat->SetMaterial(lpMat);
  1365. ((D3DFE_MATERIAL*)ULongToPtr(hMat))->pRmMat = (LPVOID)extmat;
  1366. return DD_OK;
  1367. }
  1368. //-----------------------------------------------------------------------------
  1369. //
  1370. // RLDDIRampDestroyMaterial
  1371. //
  1372. // Called to delete a ExtMaterial and all associated underlying memory and rampmap
  1373. // allocations for a given D3DFE_MATERIAL.
  1374. //
  1375. //-----------------------------------------------------------------------------
  1376. long RLDDIRampDestroyMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
  1377. {
  1378. ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
  1379. // take this element off the list before deleting it, so driver->materials
  1380. // gets updated when it should
  1381. LIST_DELETE(extmat, list);
  1382. delete extmat;
  1383. return DD_OK;
  1384. }
  1385. static long LookupMaterial(RLDDIRampLightingDriver* driver,
  1386. RLDDILookupMaterialData* data)
  1387. {
  1388. ExtMaterial* extmat = (ExtMaterial*) ULongToPtr(data->hMat);
  1389. unsigned long* texture_colors;
  1390. BOOL specular;
  1391. HRESULT error;
  1392. if ((error = extmat->FindLightingRange(&data->base, &data->size, &specular,
  1393. &texture_colors)) != DD_OK)
  1394. return error;
  1395. return DD_OK;
  1396. }
  1397. //-----------------------------------------------------------------------------
  1398. //
  1399. // RLDDIRampMaterialToPixel
  1400. //
  1401. // Call to convert a previously created material to a color for use in clearing
  1402. // the color buffer, for example.
  1403. //
  1404. //-----------------------------------------------------------------------------
  1405. unsigned long RLDDIRampMaterialToPixel(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
  1406. {
  1407. ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
  1408. RLDDILookupMaterialData data;
  1409. data.hMat = (D3DMATERIALHANDLE)((ULONG_PTR)extmat);
  1410. LookupMaterial(driver, &data);
  1411. return driver->pixelmap[data.base];
  1412. }
  1413. //-----------------------------------------------------------------------------
  1414. //
  1415. // RLDDIRampMakePaletteRGB8
  1416. //
  1417. // Call to set up the RGB8 palette and rampmap. This is a palette of 216 (== 6**3)
  1418. // entries of 6 gradations each for r, g, b. Using this palette requires
  1419. // multiplies by 6.
  1420. //
  1421. //-----------------------------------------------------------------------------
  1422. long RLDDIRampMakePaletteRGB8(RLDDIRampLightingDriver* driver)
  1423. {
  1424. RLDDIColormap* cmap = driver->rampmap->cmap;
  1425. int r, g, b;
  1426. int i = 0;
  1427. for (r = 0; r < 6; r++)
  1428. {
  1429. for (g = 0; g < 6; g++)
  1430. {
  1431. for (b = 0; b < 6; b++)
  1432. {
  1433. cmap->set_color(cmap, i, (int)((255.0/5.0) * r),
  1434. (int)((255.0/5.0) * g),
  1435. (int)((255.0/5.0) * b));
  1436. i++;
  1437. }
  1438. }
  1439. }
  1440. return DD_OK;
  1441. }
  1442. long RLDDIRampPaletteChanged(RLDDIRampLightingDriver* driver, D3DTEXTUREHANDLE hTex)
  1443. {
  1444. PD3DI_SPANTEX tex;
  1445. #ifdef DEBUG
  1446. __try
  1447. {
  1448. #endif
  1449. tex = HANDLE_TO_SPANTEX(hTex);
  1450. tex->iGeneration++;
  1451. LPDDRAWI_DDRAWSURFACE_LCL pLcl = ((LPDDRAWI_DDRAWSURFACE_INT) tex->pSurf[0])->lpLcl;
  1452. // Palette might be changed
  1453. if (tex->Format == D3DI_SPTFMT_PALETTE8 ||
  1454. tex->Format == D3DI_SPTFMT_PALETTE4)
  1455. {
  1456. if (pLcl->lpDDPalette)
  1457. {
  1458. LPDDRAWI_DDRAWPALETTE_GBL pPal = pLcl->lpDDPalette->lpLcl->lpGbl;
  1459. tex->pPalette = (PUINT32)pPal->lpColorTable;
  1460. }
  1461. }
  1462. #ifdef DEBUG
  1463. }
  1464. __except (EXCEPTION_EXECUTE_HANDLER)
  1465. {
  1466. D3D_ERR("Invalid texture handle");
  1467. }
  1468. #endif
  1469. return DD_OK;
  1470. }
  1471. //static long RampLightingService(RLDDIDriver* drv, RLDDIServiceType type,
  1472. // long arg1, void* arg2)
  1473. //{
  1474. // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv;
  1475. // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)driver;
  1476. // D3DLIGHTDATA* data;
  1477. // int mustService = FALSE;
  1478. // HRESULT err = DDERR_NOTFOUND;
  1479. //
  1480. // /*
  1481. // * Handle any services which we recognise.
  1482. // */
  1483. // switch (type) {
  1484. // case RLDDIPush:
  1485. // { RLDDIServiceProc *table = (RLDDIServiceProc *) arg2;
  1486. //
  1487. // drv->data->lighting = drv;
  1488. // if ((err = drv->service(drv, RLDDIFindRampmap, 0, &driver->rampmap)) != D3D_OK)
  1489. // return err;
  1490. // table[RLDDIPush] = RampLightingService;
  1491. // table[RLDDIPop] = RampLightingService;
  1492. // table[RLDDIApplyMaterialsUnlit] = serviceUnlight;
  1493. // table[RLDDIApplyMaterialsLit] = RampLightingService;
  1494. // table[RLDDIApplyMaterialShade] = ApplyMaterialShade;
  1495. // table[RLDDISetFogMode] = RampLightingService;
  1496. // table[RLDDISetFogStart] = RampLightingService;
  1497. // table[RLDDISetFogEnd] = RampLightingService;
  1498. // table[RLDDISetFogDensity] = RampLightingService;
  1499. // table[RLDDISetFogColor] = RampLightingService;
  1500. // table[RLDDISetLight] = RampLightingService;
  1501. // table[RLDDISetAmbientLight] = RampLightingService;
  1502. // table[RLDDILookupMaterial] = RampLightingService;
  1503. // table[RLDDISetViewport] = RampLightingService;
  1504. // table[RLDDISetMaterial] = SetMaterial;
  1505. // table[RLDDICreateMaterial] = RampLightingService;
  1506. // table[RLDDIDestroyMaterial] = RampLightingService;
  1507. // table[RLDDIFindMaterial] = RampLightingService;
  1508. // table[RLDDIMaterialChanged] = RampLightingService;
  1509. // table[RLDDISceneCapture] = RampLightingService;
  1510. // table[RLDDIClear] = RampLightingService;
  1511. // table[RLDDIClearZ] = RampLightingService;
  1512. // table[RLDDIClearBoth] = RampLightingService;
  1513. // }
  1514. // return DD_OK;
  1515. //
  1516. // case RLDDIPop:
  1517. // ReclaimMaterials(driver);
  1518. // drv->service(drv, RLDDIReleaseRampmap, 0, driver->rampmap);
  1519. // return DD_OK;
  1520. //
  1521. // case RLDDIApplyMaterialsUnlit:
  1522. // return serviceUnlight(drv, type, arg1, arg2);
  1523. //
  1524. // case RLDDIApplyMaterialsLit:
  1525. // data = (LPD3DLIGHTDATA) arg2;
  1526. // if (driver->current_material == NULL)
  1527. // return DD_OK;
  1528. // if (driver->current_material->GetMaterial()->dwRampSize == 1) {
  1529. // serviceUnlight(drv, type, arg1, arg2);
  1530. // return DD_OK;
  1531. // }
  1532. // if (sdriver->count == 1
  1533. // && (sdriver->lights->type == RLLightDirectional
  1534. // || sdriver->lights->type == RLLightParallelPoint)
  1535. // && sdriver->lights->shade > 0
  1536. // && sdriver->lights->shade <= ITOVALP(1, 8)
  1537. // && !driver->fog_enable && sdriver->lights->version==1)
  1538. // if (driver->specular_table)
  1539. // return Light1DirectionalS(driver, arg1, (LPD3DLIGHTDATA)arg2);
  1540. // else
  1541. // return Light1Directional(driver, arg1, (LPD3DLIGHTDATA)arg2);
  1542. // else
  1543. // if (driver->specular_table)
  1544. // return LightS(driver, arg1, (LPD3DLIGHTDATA)arg2);
  1545. // else
  1546. // return Light(driver, arg1, (LPD3DLIGHTDATA)arg2);
  1547. // break;
  1548. //
  1549. // case RLDDISetLight:
  1550. // {
  1551. // D3DI_LIGHT* newLights;
  1552. //
  1553. // if (arg1 > sdriver->count - 1) {
  1554. // if ((err = D3DMalloc((void**)&newLights,
  1555. // (arg1 + 1) * sizeof(D3DI_LIGHT))) != DD_OK) {
  1556. // return err;
  1557. // }
  1558. // memset(newLights, 0, (arg1 + 1) * sizeof(D3DI_LIGHT));
  1559. // memcpy(newLights, sdriver->lights, sdriver->count * sizeof(D3DI_LIGHT));
  1560. // if (sdriver->lights) {
  1561. // D3DFree(sdriver->lights);
  1562. // }
  1563. // sdriver->lights = newLights;
  1564. // sdriver->count = arg1 + 1;
  1565. // }
  1566. // }
  1567. // memcpy(&sdriver->lights[arg1], arg2, sizeof(D3DI_LIGHT));
  1568. //
  1569. // /*
  1570. // * The light vectors could be out of date.
  1571. // */
  1572. // ((RLDDITransformDriver*)drv->data->transform)->age_world = 1;
  1573. //
  1574. // return DD_OK;
  1575. //
  1576. // case RLDDISetFogMode:
  1577. // {
  1578. // D3DFOGMODE* fog = (D3DFOGMODE*) arg2;
  1579. // sdriver->fog_mode = *fog;
  1580. // driver->fog_enable = sdriver->fog_mode != D3DFOG_NONE;
  1581. //
  1582. // break;
  1583. // }
  1584. //
  1585. // case RLDDISetFogStart:
  1586. // {
  1587. // float* fog = (float*) arg2;
  1588. // sdriver->fog_start = *fog;
  1589. //
  1590. // break;
  1591. // }
  1592. // case RLDDISetFogEnd:
  1593. // {
  1594. // float* fog = (float*) arg2;
  1595. // sdriver->fog_end = *fog;
  1596. //
  1597. // break;
  1598. // }
  1599. // case RLDDISetFogDensity:
  1600. // {
  1601. // float* fog = (float*) arg2;
  1602. // sdriver->fog_density = *fog;
  1603. //
  1604. // break;
  1605. // }
  1606. //
  1607. // case RLDDISetFogColor:
  1608. // {
  1609. // driver->fog_color = arg1;
  1610. // break;
  1611. // }
  1612. //
  1613. // case RLDDIClear:
  1614. // case RLDDIClearZ:
  1615. // case RLDDIClearBoth:
  1616. // BeginSceneHook(driver);
  1617. // goto chain;
  1618. //
  1619. // case RLDDISceneCapture:
  1620. // if (arg1)
  1621. // BeginSceneHook(driver);
  1622. // else
  1623. // EndSceneHook(driver);
  1624. // goto chain;
  1625. //
  1626. // case RLDDISetAmbientLight:
  1627. // sdriver->ambient = INCPREC(FX8TOVAL((unsigned long) arg1 >> 24), 8);
  1628. // sdriver->ambient_save = arg1;
  1629. // break;
  1630. //
  1631. // case RLDDIApplyMaterialShade:
  1632. // return ApplyMaterialShade(drv, type, arg1, arg2);
  1633. //
  1634. // case RLDDILookupMaterial:
  1635. // return LookupMaterial(driver, (RLDDILookupMaterialData*) arg2);
  1636. //
  1637. // case RLDDISetMaterial:
  1638. // return SetMaterial(drv, type, arg1, arg2);
  1639. //
  1640. // case RLDDICreateMaterial:
  1641. // return CreateMaterial(driver, (LPD3DMATERIALHANDLE)arg1, (LPD3DMATERIAL)arg2);
  1642. //
  1643. // case RLDDIDestroyMaterial:
  1644. // return DestroyMaterial(driver, (D3DMATERIALHANDLE)arg1);
  1645. //
  1646. // case RLDDIFindMaterial:
  1647. // {
  1648. // LPD3DMATERIAL* lplpMat = (LPD3DMATERIAL*)arg2;
  1649. // ExtMaterial* extmat = (ExtMaterial*)arg1;
  1650. //
  1651. // *lplpMat = extmat->GetMaterial();
  1652. // }
  1653. // return DD_OK;
  1654. //
  1655. // case RLDDIMaterialChanged:
  1656. // {
  1657. // ExtMaterial* extmat = (ExtMaterial*)arg1;
  1658. //
  1659. // extmat->SetMaterial((LPD3DMATERIAL) arg2);
  1660. //
  1661. // return DD_OK;
  1662. // }
  1663. //
  1664. // case RLDDISetViewport:
  1665. // driver->viewport_id = arg1;
  1666. // /*
  1667. // * Chain to the next driver.
  1668. // */
  1669. // if (drv->next)
  1670. // return drv->next->service(drv->next, type, arg1, arg2);
  1671. // return DD_OK;
  1672. //
  1673. // default: chain:
  1674. // mustService = TRUE;
  1675. // }
  1676. //
  1677. // if (drv->next)
  1678. // err = (HRESULT) drv->next->service(drv->next, type, arg1, arg2);
  1679. //
  1680. // return (mustService || err != DDERR_NOTFOUND)? err : DD_OK;
  1681. //}
  1682. //
  1683. //unsigned long* RLDDIRampFindTexturePixels(RLDDIDriver* drv, D3DMATERIALHANDLE hMat)
  1684. //{
  1685. // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv;
  1686. // ExtMaterial* extmat = (ExtMaterial*) hMat;
  1687. // PD3DI_SPANTEX tex = HANDLE_TO_SPANTEX(extmat->GetMaterial()->hTexture);
  1688. // unsigned long base, size;
  1689. // unsigned long* texture_colors;
  1690. // HRESULT error;
  1691. //
  1692. // if (!tex) {
  1693. // return NULL;
  1694. // }
  1695. // driver = (RLDDIRampLightingDriver*) tex->owner;
  1696. //
  1697. // if (extmat == NULL)
  1698. // return NULL;
  1699. // if ((error = extmat->FindLightingRange(&base, &size, &texture_colors)) != DD_OK)
  1700. // return NULL;
  1701. //
  1702. // return texture_colors;
  1703. //}
  1704. //
  1705. //void*GetMaterialTextureHandle(RLDDIDriver* drv)
  1706. //{
  1707. // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv;
  1708. // ExtMaterial* extmat = driver->current_material;
  1709. // PD3DI_SPANTEX tex = NULL;
  1710. // if(extmat){
  1711. // LPD3DMATERIAL mat = extmat->GetMaterial();
  1712. // if (mat && mat->hTexture)
  1713. // tex = HANDLE_TO_SPANTEX(mat->hTexture);
  1714. // }
  1715. //
  1716. // return tex;
  1717. //}
  1718. define(`d_Ramp_ScaleImage', `
  1719. dnl
  1720. define(`d_BPP', eval($1/8))dnl
  1721. define(`d_Type', ifelse($1, 8, `UINT8', $1, 16, `UINT16', $1, 24, `UINT8', $1, 32, `UINT32'))dnl
  1722. dnl
  1723. void Ramp_Mono_ScaleImage_$1(PD3DI_RASTCTX pCtx, D3DMATERIALHANDLE hMat, LPD3DRECT pRect)
  1724. {
  1725. RLDDIRampLightingDriver *pLtDriver =
  1726. (RLDDIRampLightingDriver*)pCtx->pRampDrv;
  1727. RLDDIRampSetMaterial(pLtDriver, hMat);
  1728. PD3DI_SPANTEX pTex;
  1729. pTex = HANDLE_TO_SPANTEX(((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat.hTexture);
  1730. if (pLtDriver && pLtDriver->current_material)
  1731. {
  1732. DWORD dwBase;
  1733. DWORD dwSize;
  1734. unsigned long* pixels;
  1735. unsigned long* map = (unsigned long*)pCtx->pRampMap;
  1736. BOOL bSpecular;
  1737. // Update the ramp info. in RastCtx
  1738. pLtDriver->current_material->FindLightingRange(
  1739. &dwBase,
  1740. &dwSize,
  1741. &bSpecular,
  1742. (unsigned long**)&pixels);
  1743. // Make sure DD Palette is updated after it gets set by FindLightingRange
  1744. RLDDIRampUpdateDDPalette(pCtx);
  1745. LPDDRAWI_DDRAWSURFACE_LCL pLcl =
  1746. ((LPDDRAWI_DDRAWSURFACE_INT)(pTex->pSurf[0]))->lpLcl;
  1747. int iTexWidth = pLcl->lpGbl->wWidth;
  1748. int iTexHeight = pLcl->lpGbl->wHeight;
  1749. int src_width = pLcl->lpGbl->lPitch;
  1750. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pCtx->pDDS))->lpLcl;
  1751. int iSurfWidth = pLcl->lpGbl->wWidth;
  1752. int iSurfHeight = pLcl->lpGbl->wHeight;
  1753. int x1 = pRect->x1;
  1754. int y1 = pRect->y1;
  1755. int x2 = pRect->x2;
  1756. int y2 = pRect->y2;
  1757. int width = x2 - x1;
  1758. int height = y2 - y1;
  1759. FLOAT scalex = (FLOAT)iSurfWidth/(FLOAT)iTexWidth;
  1760. FLOAT scaley = (FLOAT)iSurfHeight/(FLOAT)iTexHeight;
  1761. int dstx = x1;
  1762. int dsty = y1;
  1763. unsigned char* src = pTex->pBits[0];
  1764. int src_skip;
  1765. unsigned char* dst = pCtx->pSurfaceBits + dstx * d_BPP + dsty * pCtx->iSurfaceStride;
  1766. int dst_skip = pCtx->iSurfaceStride - width * d_BPP;
  1767. int i;
  1768. if ((scalex == 1.0F) && (scaley == 1.0F)) {
  1769. src = src + src_width * y1 + x1;
  1770. src_skip = src_width - width;
  1771. do {
  1772. i = width;
  1773. do {
  1774. ifelse($1, 24, `
  1775. *(d_Type*)(dst+0) = ((d_Type*)(&map[pixels[*src]]))[0];
  1776. *(d_Type*)(dst+1) = ((d_Type*)(&map[pixels[*src]]))[1];
  1777. *(d_Type*)(dst+2) = ((d_Type*)(&map[pixels[*src++]]))[2];',`
  1778. *(d_Type*)dst = (d_Type)map[pixels[*src++]];')
  1779. dst += d_BPP;
  1780. } while (--i);
  1781. src += src_skip;
  1782. dst += dst_skip;
  1783. } while (--height);
  1784. } else {
  1785. FLOAT mu, mv;
  1786. FLOAT u, v, u_start;
  1787. /*
  1788. * Turn the scale values into deltas which we can use to
  1789. * interpolate in the texture.
  1790. */
  1791. mu = 1.0f/scalex;
  1792. mv = 1.0f/scaley;
  1793. /*
  1794. * Work out the real source address in the unscaled texture.
  1795. * ~.5 offset makes the result stable for even scales which are common.
  1796. */
  1797. u = ((FLOAT)x1+0.4999f) * mu;
  1798. v = ((FLOAT)y1+0.4999f) * mv;
  1799. u_start = u;
  1800. do {
  1801. unsigned char* src_line = src + src_width * int(v);
  1802. u = u_start;
  1803. i = width;
  1804. do {
  1805. ifelse($1, 24, `
  1806. *(d_Type*)(dst+0) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[0];
  1807. *(d_Type*)(dst+1) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[1];
  1808. *(d_Type*)(dst+2) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[2];',`
  1809. *(d_Type*)dst = (d_Type)map[pixels[src_line[int(u)]]];')
  1810. dst += d_BPP;
  1811. u += mu;
  1812. } while (--i);
  1813. v += mv;
  1814. dst += dst_skip;
  1815. } while (--height);
  1816. }
  1817. }
  1818. }
  1819. ')dnl
  1820. d_Ramp_ScaleImage(8)
  1821. d_Ramp_ScaleImage(16)
  1822. d_Ramp_ScaleImage(24)
  1823. d_Ramp_ScaleImage(32)