|
|
//---------------------------------------------------------------------------- // // rmprov.cpp // // Declares classes for ramp material handling. // // Copyright (C) Microsoft Corporation, 1997. // //----------------------------------------------------------------------------
include(`m4hdr.mh')dnl #include "pch.cpp" #pragma hdrstop
//#define _D3DHAL_H_ //typedef void* LPD3DHAL_CALLBACKS; //typedef void* LPD3DHAL_CALLBACKS2; //typedef void* LPD3DHAL_TRANSFORMLIGHTCALLBACKS; //typedef void* LPD3DHAL_TEXTURE3CALLBACKS; //typedef void* LPD3DHAL_GLOBALDRIVERDATA; //typedef void* LPD3DHAL_D3DEXTENDEDCAPS; // //#include <assert.h> //#include <string.h> //#include <math.h> // //extern "C" { //#include "driver.h" //#include "lightdrv.h" //#include "fsqrt.h" //#include "lists.h" //#include "ramplt.h" //#include "rampmap.h" //#include "transfm.h" //#include "handle.h" //#include "gentex.h" //#include "dmath.h" //#include "ramplti.h" //#include "dpf.h" // //#include <d3di.h> //#include "..\include\genras.h" //} // //static void Destroy(RLDDIDriver* drv); //static long RampLightingService(RLDDIDriver* drv, RLDDIServiceType type, // long arg1, void* arg2); // //#define SPEC(tab, s) tab->table[QVALTOFXP(s, 8)] //#define NEXT_X(type, x, size) ((type*)((char*) (x) + (size))) //#define NEXT_ELEMENT(el, size) NEXT_X(D3DLIGHTINGELEMENT, el, size) //#define NEXT_COLOR(col, size) NEXT_X(unsigned long, col, size) //#define NEXT_VERTEX(v, size) NEXT_X(D3DTLVERTEX, v, size) // #define CVAL_TO_RGBA(rgb) RGBA_MAKE((int)(255.0 * (rgb)->r), \ (int)(255.0 * (rgb)->g), \ (int)(255.0 * (rgb)->b), \ (int)(255.0 * (rgb)->a))
//static HRESULT LitFog(RLDDIRampLightingDriver* driver, // int count, D3DTLVERTEX* v, size_t v_size, // Workspace* wp); static void ReclaimMaterials(RLDDIRampLightingDriver* driver); //void vectordvNormalise12(D3DVECTOR* v); // //static D3DCOLOR cval_to_cola(D3DCOLORVALUE* rgb) //{ // return CVAL_TO_RGBA(rgb); //} //
static int InitRampmap(PD3DI_RASTCTX pCtx, RLDDIRampLightingDriver* driver, RLDDIRampmap** rampmap_return) { RLDDIColormap* cmap; RLDDIRampmap* rampmap; RLDDIColorAllocator* alloc; LPDDRAWI_DDRAWSURFACE_LCL pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pCtx->pDDS))->lpLcl;
if ((pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE4) || (pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE8)) { if (pCtx->iSurfaceType == D3DI_SPTFMT_PALETTE4) { driver->palette = RLDDICreatePalette(pCtx, 16); } else { driver->palette = RLDDICreatePalette(pCtx, 256); } alloc = &driver->palette->alloc;
// Initialize palette PALETTEENTRY ddppe[256]; HRESULT ddrval; LPDIRECTDRAWPALETTE lpPal; ddrval = pCtx->pDDS->GetPalette(&lpPal); ddrval = lpPal->GetEntries(0, 0, 256, ddppe);
memset(driver->ddpalette, 0, sizeof(PALETTEENTRY) * 256); for (int i = 0; i < 256; i++) { DWORD dwFlags = ddppe[i].peFlags & (D3DPAL_FREE | D3DPAL_READONLY | D3DPAL_RESERVED); driver->ddpalette[i].peFlags = ddppe[i].peFlags; switch (dwFlags) { case D3DPAL_FREE: D3D_INFO(6, "(Rast) Color %d is free", i); RLDDIPaletteFreeColor(driver->palette, i); break; case D3DPAL_READONLY: D3D_INFO(6, "(Rast) Color %d is readonly", i); RLDDIPaletteSetColor(driver->palette, i, ddppe[i].peRed, ddppe[i].peGreen, ddppe[i].peBlue); driver->ddpalette[i].peRed = ddppe[i].peRed; driver->ddpalette[i].peGreen = ddppe[i].peGreen; driver->ddpalette[i].peBlue = ddppe[i].peBlue; break; case D3DPAL_RESERVED: D3D_INFO(6, "(Rast) Color %d is reserved", i); break; default: D3D_ERR("(Rast) Unknown flag passed in peFlags"); break; } } } else {
DWORD dwRMask, dwGMask, dwBMask; if (pLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT) { dwRMask = pLcl->lpGbl->ddpfSurface.dwRBitMask; dwGMask = pLcl->lpGbl->ddpfSurface.dwGBitMask; dwBMask = pLcl->lpGbl->ddpfSurface.dwBBitMask; } else { dwRMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwRBitMask; dwGMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwGBitMask; dwBMask = pLcl->lpGbl->lpDD->vmiData.ddpfDisplay.dwBBitMask; }
driver->rgbmap = RLDDICreateRGBMap(dwRMask,dwGMask,dwBMask); alloc = &driver->rgbmap->alloc; }
cmap = RLDDICreateIndirectColormap(alloc, 32768);
if (cmap == NULL || cmap->priv == NULL) return DDERR_OUTOFMEMORY;
driver->pixelmap = RLDDIIndirectColormapGetMap(cmap); pCtx->pRampMap = (PUINT32)driver->pixelmap; rampmap = RLDDICreateRampmap(cmap);
if (rampmap) *rampmap_return = rampmap; else return DDERR_OUTOFMEMORY;
return DD_OK; }
static void ReleaseRampmap(RLDDIRampmap* rampmap) { if (rampmap != NULL) { RLDDIColormap* cmap = rampmap->cmap;
RLDDIDestroyRampmap(rampmap); if (cmap != NULL) cmap->destroy(cmap); } }
//----------------------------------------------------------------------------- // // RLDDIRampCreate // // Creates the original RLDDIRampLightingDriver with associated lists. The // pointer returned is kept in pCtx->pRampDrv. // //----------------------------------------------------------------------------- RLDDIRampLightingDriver* RLDDIRampCreate(PD3DI_RASTCTX pCtx/*int width, int height, LPDIRECT3DDEVICEI lpD3DDevI*/) { RLDDIRampLightingDriver* driver; RLDDISoftLightingDriver* sdriver; int i;
if (D3DMalloc((void**) &driver, sizeof(RLDDIRampLightingDriver))) return NULL; memset(driver, 0, sizeof(RLDDIRampLightingDriver));
sdriver = (RLDDISoftLightingDriver*)driver;
pCtx->pRampDrv = driver;
// sdriver->driver.prev = NULL; // sdriver->driver.next = NULL; // sdriver->driver.width = width; // sdriver->driver.height = height; // sdriver->driver.destroy = Destroy; // sdriver->driver.service = RampLightingService; // sdriver->driver.lpD3DDevI = lpD3DDevI;
/* * Initialise driver specific fields. */ // sdriver->count = 0; // sdriver->lights = NULL;
LIST_INITIALIZE(&driver->materials); LIST_INITIALIZE(&driver->orphans);
CIRCLE_QUEUE_INITIALIZE(&driver->agequeue,AgeList); for (i = 0; i < AGE_MAX; i++) { LIST_INITIALIZE(&driver->agelists[i].agelist); CIRCLE_QUEUE_INSERT_END(&driver->agequeue, AgeList, &driver->agelists[i], list); } driver->active = CIRCLE_QUEUE_FIRST(&driver->agequeue); driver->already_aged = FALSE;
LIST_INITIALIZE(&driver->rmactive); for (i = 0; i < HASH_SIZE; i++) LIST_INITIALIZE(&driver->hash[i]);
// LIST_INITIALIZE(&driver->specular_tables); // driver->specular_table = NULL;
driver->fog_enable = FALSE; driver->fog_color = FALSE;
sdriver->fog_mode = D3DFOG_NONE;
if (InitRampmap(pCtx, driver, &driver->rampmap) == S_OK) return /*(RLDDIDriver*)*/ driver; else return NULL; }
//----------------------------------------------------------------------------- // // RLDDIRampDestroy // // Destroys a RLDDIRampLightingDriver with all associated objects and memory. // The pCtx->pRampDrv pointer should be set to NULL after this occurs. // //----------------------------------------------------------------------------- void RLDDIRampDestroy(RLDDIRampLightingDriver* drv) { // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)drv; RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv;
// if (sdriver->lights) { // D3DFree(sdriver->lights); // } // // { // SpecularTable* spec; // SpecularTable* spec_next; // // for (spec = LIST_FIRST(&driver->specular_tables); // spec; // spec = spec_next) { // spec_next = LIST_NEXT(spec,list); // D3DFree(spec); // } // } //
ReclaimMaterials(driver);
ReleaseRampmap(driver->rampmap);
RLDDIDestroyRGBMap(driver->rgbmap);
// this must be done AFTER ReclaimMaterials if (driver->palette) { RLDDIDestroyPalette(driver->palette); }
D3DFree(drv); }
static void ReclaimMaterials(RLDDIRampLightingDriver* driver) { /* * Reclaim materials. */ for (ExtMaterial* extmat = LIST_FIRST(&driver->materials); extmat; extmat = LIST_FIRST(&driver->materials)) { delete extmat; } for (IntMaterial* intmat = LIST_FIRST(&driver->orphans); intmat; intmat = LIST_FIRST(&driver->orphans)) { delete intmat; }
/* * After destroying all the materials, there should be nothing * left in the ramp material hash tables. Lets just make sure. */ for (int i = 0; i < HASH_SIZE; i++) { DDASSERT(LIST_FIRST(&driver->hash[i]) == NULL); } }
ExtMaterial::ExtMaterial(RLDDIRampLightingDriver* adriver, D3DMATERIALHANDLE hMat) { D3D_INFO(7, "(Rast) Making new ExtMaterial(%08x)", this); driver = adriver; generation = 0; texture_generation = 0; texture = NULL; LIST_INITIALIZE(&intlist); }
ExtMaterial::~ExtMaterial() { D3D_INFO(7, "(Rast) Destroying ExtMaterial(%08x)", this);
IntMaterial* intmat;
/* * Transfer active internal materials to the driver's orphans list * to be reclaimed after Clear. Free any inactive ones now. */ while (LIST_FIRST(&intlist)) { intmat = LIST_FIRST(&intlist); if (intmat->IsActive()) { D3D_INFO(7, "(Rast) IntMaterial(%08x) is still active, moving to orphan list", intmat); intmat->Orphan(); } else delete intmat; }
if (driver->current_material == this) { D3D_WARN(3, "(Rast) Destroying current material, setting to NULL"); driver->current_material = NULL; } }
#undef DPF_MODNAME #define DPF_MODNAME "ExtMaterial::SetMaterial"
void ExtMaterial::SetMaterial(D3DMATERIAL* lpMat) { D3D_INFO(7, "(Rast) Setting value of ExtMaterial(%08x)", this); if (!memcmp(&mat, lpMat, sizeof(D3DMATERIAL))) { D3D_WARN(7, "(Rast) ExtMaterial::SetMaterial: New value is identical to old value, ignoring"); return; } mat = *lpMat; if (mat.hTexture) { PD3DI_SPANTEX tex;
#ifdef DEBUG __try { #endif tex = HANDLE_TO_SPANTEX(mat.hTexture); texture_generation = tex->iGeneration; texture = tex; #ifdef DEBUG } __except (EXCEPTION_EXECUTE_HANDLER) { D3D_ERR("Invalid texture handle"); mat.hTexture = 0; texture = NULL; } #endif } else texture = NULL; Age(); }
void ExtMaterial::Age() { IntMaterial* intmat;
/* * Transfer active internal materials to the driver's orphans list * to be reclaimed after Clear. Free any inactive ones now. */ while (LIST_FIRST(&intlist)) { intmat = LIST_FIRST(&intlist); if (intmat->IsActive()) { D3D_INFO(7, "(Rast) IntMaterial(%08x) is still active, moving to orphan list", intmat); intmat->Orphan(); } else delete intmat; }
generation++; }
IntMaterial* ExtMaterial::FindIntMaterial() { IntMaterial* intmat;
if (texture) { D3D_INFO(7, "(Rast) Checking texture in ExtMaterial(%08x) for new palette or texture swap", this); PD3DI_SPANTEX tex; tex = HANDLE_TO_SPANTEX(mat.hTexture); if (tex != texture) { D3D_WARN(1, "(Rast) Textures swapped, discarding old materials"); texture_generation = tex->iGeneration; texture = tex; Age(); } else if (texture_generation != tex->iGeneration) { D3D_WARN(1, "(Rast) Texture has changed, discarding old materials"); texture_generation = tex->iGeneration; Age(); } }
D3D_INFO(7, "(Rast) Searching ExtMaterial(%08x) for an IntMaterial", this); for (intmat = LIST_FIRST(&intlist); intmat; intmat = LIST_NEXT(intmat,list)) { if (intmat->Valid()) { /* * Found it. Move to the front of the list to optimise searches. */ LIST_DELETE(intmat, list); LIST_INSERT_ROOT(&intlist, intmat, list); D3D_INFO(7, "(Rast) IntMaterial(%08x) found", intmat); return intmat; } } D3D_INFO(7, "(Rast) No matching IntMaterial found, creating new one"); return new IntMaterial(this); }
/* * Find what range of values lighting should take. The base is the * pixel value (in fixed point) of the dark end of the material. The * shift value is user to convert a 0.16 fixed point shade into the * range needed for the material. e.g. * * pixel = base + (VALTOFX8(shade) << shift); * */ HRESULT ExtMaterial::FindLightingRange(unsigned long* base, unsigned long* size, BOOL* specular, unsigned long** texture_colors) { IntMaterial* intmat;
D3D_INFO(7, "(Rast) Finding color ranges for ExtMaterial(%08x)", this); intmat = FindIntMaterial(); if (intmat == NULL) return DDERR_NOTFOUND;
/* * Delegate to the internal material. */ D3D_INFO(7, "(Rast) Using IntMaterial(%08x) for ExtMaterial(%08x)", intmat, this); return intmat->FindLightingRange(base, size, specular, texture_colors); }
IntMaterial::IntMaterial(ExtMaterial* anextmat) { D3D_INFO(7, "(Rast) Creating new IntMaterial(%08x) for ExtMaterial(%08x)", this, extmat); /* * Remember the driver object. */ extmat = anextmat; driver = extmat->driver;
RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*) driver;
/* * Initialise stuff so that if we have to abort, the destructor can * clean up. */ active = FALSE; ramps = NULL; colors = NULL; ambient = sdriver->ambient; viewport_id = driver->viewport_id; fog_enable = driver->fog_enable; fog_color = driver->fog_color; generation = extmat->generation;
/* * Put us on the list of internal materials owned by our creator. */ LIST_INSERT_ROOT(&extmat->intlist, this, list);
/* * Add to the age=1 list for material use tracking. */ AgeList* age1 = CIRCLE_QUEUE_NEXT(&driver->agequeue,driver->active,list); age = age1; LIST_INSERT_ROOT(&age1->agelist, this, agelist);
/* * Record the current external material's D3DMATERIAL. Note that this * can change at any time. We need a snapshot. */ mat = extmat->mat;
PD3DI_SPANTEX tex; if (mat.hTexture) tex = HANDLE_TO_SPANTEX(mat.hTexture); else tex = NULL;
if (tex == NULL) ramp_count = 1; else ramp_count = tex->iPaletteSize;
ramps = new RampMaterial*[ramp_count]; if (ramps == NULL) { D3D_ERR("Out of memory creating IntMaterial"); delete this; //this = NULL; return; } colors = new unsigned long[ramp_count];
memset(ramps, 0, ramp_count * sizeof(RampMaterial*));
D3DMATERIAL tmat; tmat = mat; tmat.hTexture = 0L; LPPALETTEENTRY palette = NULL; if (tex) palette = (LPPALETTEENTRY)tex->pPalette; for (int i = 0; i < ramp_count; i++) { if (tex) { tmat.ambient.r = (float)((palette->peRed * mat.ambient.r) / 255.0); tmat.ambient.g = (float)((palette->peGreen * mat.ambient.g) / 255.0); tmat.ambient.b = (float)((palette->peBlue * mat.ambient.b) / 255.0); tmat.ambient.a = mat.ambient.a; tmat.diffuse.r = (float)((palette->peRed * mat.diffuse.r) / 255.0); tmat.diffuse.g = (float)((palette->peGreen * mat.diffuse.g) / 255.0); tmat.diffuse.b = (float)((palette->peBlue * mat.diffuse.b) / 255.0); tmat.diffuse.a = mat.diffuse.a; palette++; } ramps[i] = RampMaterial::Find(driver, &tmat); if (ramps[i] == NULL) { D3D_ERR("Can't find RampMaterial for IntMaterial"); delete this; //this = NULL; return; } } }
IntMaterial::~IntMaterial() { D3D_INFO(9, "(Rast) Destroying IntMaterial(%08x)", this);
/* * Give up our colors. */ if (active) Deactivate();
/* * Remove from lists. */ LIST_DELETE(this, list); LIST_DELETE(this, agelist);
/* * Release underlying ramp materials and memory. */ if (ramps) { for (int i = 0; i < ramp_count; i++) if (ramps[i]) ramps[i]->Release(); delete ramps; } if (colors) delete colors; }
int IntMaterial::Valid() { RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*) driver;
/* * Ambient only matters for lit materials. */ if (mat.dwRampSize > 1 && ambient != sdriver->ambient) return FALSE;
return (viewport_id == driver->viewport_id && fog_enable == driver->fog_enable && fog_color == driver->fog_color && generation == extmat->generation); }
HRESULT IntMaterial::FindLightingRange(unsigned long* base, unsigned long* size, BOOL* specular, unsigned long** texture_colors) { HRESULT error;
D3D_INFO(7, "(Rast) Finding color ranges for IntMaterial(%08x)", this);
/* * Make sure the material is active. */ if ((error = Activate()) != DD_OK) { D3D_ERR("Can't activate IntMaterial"); return error; }
/* * For non-textured materials, the base is the start of the * color range. For textured materials, the base is zero and * texture_colors is set to the array containing the color bases. */ if (mat.hTexture) { // until we find a reason to do otherwise, have base // be just a plain color index offset (no alpha, and no shift // up by 8 // *base = CI_MAKE((int)(mat.diffuse.a * 255.0), 0, 0); *base = 0; *texture_colors = colors; } else { // *base = CI_MAKE((int)(mat.diffuse.a * 255.0), colors[0], 0); *base = colors[0]; } *size = mat.dwRampSize;
// same code as in SetColorsStd and SetColorsFog if ((*size <= 2) || ((mat.specular.r == 0.0) && (mat.specular.g == 0.0) && (mat.specular.b == 0.0))) *specular = FALSE; else *specular = TRUE;
return DD_OK; }
HRESULT IntMaterial::Activate() { HRESULT error;
/* * If we are already active, just make sure we are on the right list. */ if (active) { D3D_INFO(7, "(Rast) IntMaterial(%08x) is already active", this); if (age != driver->active) { D3D_INFO(7, "(Rast) Moving IntMaterial(%08x) to list %08x", this, driver->active); LIST_DELETE(this, agelist); LIST_INSERT_ROOT(&driver->active->agelist, this, agelist); age = driver->active; } else { D3D_INFO(7, "(Rast) IntMaterial(%08x) is already on the active list", this); } return DD_OK; }
D3D_INFO(6, "(Rast) Activating IntMaterial(%08x)", this);
/* * Activate all the underlying materials and record their bases. */ for (int i = 0; i < ramp_count; i++) { if ((error = ramps[i]->Activate()) != DD_OK) { D3D_WARN(0, "Failed to activate RampMaterial(%08x) for IntMaterial(%08x)", ramps[i], this); /* * Failed to activate all the underlying RampMaterials. * Deactivate any which we did manage. */ for (int j = 0; j < i; j++) ramps[j]->Deactivate(); return error; } colors[i] = ramps[i]->Base(); }
/* * We are now active, so remember and put us on the age=0 list. */ D3D_INFO(7, "(Rast) Moving IntMaterial(%08x) to list %08x", this, driver->active); active = TRUE; LIST_DELETE(this, agelist); LIST_INSERT_ROOT(&driver->active->agelist, this, agelist); age = driver->active;
return DD_OK; }
void IntMaterial::Deactivate() { if (!active) return;
D3D_INFO(6, "(Rast) Deactivating IntMaterial(%08x)", this);
for (int i = 0; i < ramp_count; i++) ramps[i]->Deactivate();
active = FALSE; }
void IntMaterial::Orphan() { LIST_DELETE(this, list); LIST_INSERT_ROOT(&driver->orphans, this, list); }
RampMaterial::RampMaterial(RLDDIRampLightingDriver* adriver, D3DMATERIAL* lpMat, float anambient) : driver(adriver) { D3D_INFO(6, "(Rast) Creating new RampMaterial(%08x) color=[%d,%d,%d] size=%d", this, (int)(255 * lpMat->diffuse.r), (int)(255 * lpMat->diffuse.g), (int)(255 * lpMat->diffuse.b), lpMat->dwRampSize);
unsigned int hash = CVAL_TO_RGBA(&lpMat->diffuse) % HASH_SIZE; /* XXX */
LIST_INSERT_ROOT(&driver->hash[hash], this, hash); LIST_INITIALIZE(&sharers);
usage = 1; active = 0;
ramp = NULL; owner = FALSE; ambient = anambient; mat = *lpMat; fog_enable = driver->fog_enable; fog_color = driver->fog_color; LIST_INITIALIZE_MEMBER(this,deferredlist); }
RampMaterial::~RampMaterial() { D3D_INFO(9, "(Rast) Destroying RampMaterial(%08x)", this);
DDASSERT(usage == 0); // don't destroy stuff, call Release DDASSERT(active == 0); // don't Release an active material
LIST_DELETE(this, hash); }
int RampMaterial::MaterialSame(D3DMATERIAL* mat1, D3DMATERIAL* mat2) { if (mat1->ambient.r == mat2->ambient.r && mat1->ambient.g == mat2->ambient.g && mat1->ambient.b == mat2->ambient.b && mat1->diffuse.r == mat2->diffuse.r && mat1->diffuse.g == mat2->diffuse.g && mat1->diffuse.b == mat2->diffuse.b && mat1->specular.r == mat2->specular.r && mat1->specular.g == mat2->specular.g && mat1->specular.b == mat2->specular.b && mat1->emissive.r == mat2->emissive.r && mat1->emissive.g == mat2->emissive.g && mat1->emissive.b == mat2->emissive.b && mat1->power == mat2->power && mat1->dwRampSize == mat2->dwRampSize) return 1; return 0; }
#define ABS(a) ((a) > 0 ? (a) : -(a))
int RampMaterial::RGBDist(D3DCOLORVALUE* rgb1, D3DCOLORVALUE* rgb2) { return ABS((int)(255.0 * (rgb1->r - rgb2->r))) + ABS((int)(255.0 * (rgb1->g - rgb2->g))) + ABS((int)(255.0 * (rgb1->b - rgb2->b))); }
int RampMaterial::CompareMaterials(D3DMATERIAL* mat1, D3DMATERIAL* mat2) { return (RGBDist(&mat1->ambient, &mat2->ambient) + RGBDist(&mat1->diffuse, &mat2->diffuse) + RGBDist(&mat1->specular, &mat2->specular) + ABS((int)mat1->power - (int)mat2->power)); }
RampMaterial* RampMaterial::Find(RLDDIRampLightingDriver* driver, D3DMATERIAL* mat) { D3D_INFO(8, "(Rast) Searching for RampMaterial");
unsigned int hash = CVAL_TO_RGBA(&mat->diffuse) % HASH_SIZE; /* XXX */ RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)driver; RampMaterial* rm = NULL; float ambient;
if (mat->dwRampSize > 1 && !driver->fog_enable) ambient = sdriver->ambient; else ambient = 0.0f;
for (rm = LIST_FIRST(&driver->hash[hash]); rm; rm = LIST_NEXT(rm,hash)) { if (MaterialSame(&rm->mat, mat) && rm->ambient == ambient && driver->fog_enable == rm->fog_enable && driver->fog_color == rm->fog_color) break; } if (rm) { rm->usage++; D3D_INFO(7, "(Rast) RampMaterial(%08x) found, usage is now %d", rm, rm->usage); return rm; } else { D3D_INFO(7, "(Rast) No matching material found, creating new one"); return new RampMaterial(driver, mat, ambient); } }
void RampMaterial::Release() { usage--; D3D_INFO(7, "(Rast) Releasing RampMaterial(%08x), usage is now %d", this, usage); if (usage == 0) delete this; }
HRESULT RampMaterial::Activate() { HRESULT error;
D3D_INFO(6, "(Rast) Activating RampMaterial(%08x)", this);
/* * The first time we are activated, allocate some colors. */ if (active == 0) { if ((error = AllocateColors()) != DD_OK) return error; }
active++; DDASSERT(active <= usage);
return DD_OK; }
void RampMaterial::Deactivate() { D3D_INFO(6, "(Rast) Deactivating RampMaterial(%08x)", this);
active--; DDASSERT(active >= 0);
/* * Free our colors if none of our users are active. */ if (active == 0) FreeColors(); }
unsigned long RampMaterial::Base() { DDASSERT(ramp != NULL); D3D_INFO(7, "(Rast) Base pixel for RampMaterial(%08x) is %d", this, ramp->base); return ramp->base; }
HRESULT RampMaterial::AllocateColors() { D3D_INFO(6, "(Rast) Allocating colors for RampMaterial(%08x)", this);
DDASSERT(ramp == NULL);
ramp = RLDDIRampmapAllocate(driver->rampmap, mat.dwRampSize);
if (ramp) { D3D_INFO(7, "(Rast) Ramp(%08x) range %d..%d allocated for RampMaterial(%08x)", ramp, ramp->base, ramp->base + ramp->size - 1, this);
/* * We got a ramp, so mark this material as owning the ramp and add * it to the active list. */ owner = TRUE; SetColors();
/* * This material now owns the ramp, so place it on the active list. */ D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to active material list", this); LIST_INSERT_ROOT(&driver->rmactive, this, list);
/* * No sharers yet. */ LIST_INITIALIZE(&sharers); } else { D3D_INFO(7, "(Rast) No Ramp allocated, searching for closest active material");
/* * Search the active list for a similar material and share its ramp. */ RampMaterial *t; RampMaterial *best; int closeness, c;
best = NULL; closeness = INT_MAX; do { for (t = LIST_FIRST(&driver->rmactive); t; t = LIST_NEXT(t,list)) { if (t->ramp) { if (mat.dwRampSize != t->mat.dwRampSize) continue;
c = CompareMaterials(&mat, &t->mat); if (c < closeness) { best = t; closeness = c; } } } if (best == NULL) { t = LIST_FIRST(&driver->rmactive); mat.dwRampSize = t->mat.dwRampSize; D3D_WARN(2, "(Rast) No matching ramp found in palette"); D3D_WARN(2, "(Rast) Changing material rampsize to match first list entry"); } } while (!best);
DDASSERT(best != NULL);
/* * Add the material to the list of sharers for the ramp owner. If * the owner later stops using the ramp, it will be inherited by the * first material on the sharers list. */ D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) as sharer of RampMaterial(%08x)", this, best); LIST_INSERT_ROOT(&best->sharers, this, list); ramp = best->ramp; owner = FALSE; }
return DD_OK; }
void RampMaterial::FreeColors() { D3D_INFO(6, "(Rast) Freeing colors for RampMaterial(%08x)", this);
DDASSERT(ramp != NULL);
/* * First remove us from either rmactive or owner->sharers depending on * whether we are sharing a ramp. */ LIST_DELETE(this, list);
/* * If we were waiting for a deferred call to SetColors, make sure * it doesn't happen. */ if (!LIST_ORPHAN_MEMBER(this,deferredlist)) { D3D_INFO(7, "(Rast) Removing RampMaterial(%08x) from deferred SetColor list", this); LIST_DELETE(this, deferredlist); }
/* * If we owned the ramp, then either donate it to a sharer or free it * as appropriate. */ if (owner) { D3D_INFO(7, "(Rast) RampMaterial(%08x) owned Ramp(%08x)", this, ramp); if (LIST_FIRST(&sharers)) { /* * There were sharers, so donate the ramp to the first one and * make the others sharers of the new owner. */ RampMaterial* new_owner = LIST_FIRST(&sharers); RampMaterial* t; RampMaterial* tnext;
D3D_INFO(7, "(Rast) New owner of Ramp(%08x) is RampMaterial(%08x)", ramp, new_owner); new_owner->owner = TRUE; /* * Defer setting the colours until the next frame to avoid * palette flashing. Check to see if it is already there. */ if (LIST_ORPHAN_MEMBER(new_owner,deferredlist)) { D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to deferred SetColor list", this); LIST_INSERT_ROOT(&driver->rmdeferred, new_owner, deferredlist); }
/* * Remove from the sharers list and add to the active list. * Clear the new owner's sharers list so that we can add * the rest of the old sharers to it. */ D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) to active material list", new_owner); LIST_DELETE(new_owner, list); LIST_INSERT_ROOT(&driver->rmactive, new_owner, list); LIST_INITIALIZE(&new_owner->sharers);
/* * Traverse the rest of the sharers, and add them as * sharers of the new owner if they are still using the * ramp, otherwise add them to the inactive list. */ for (t = LIST_FIRST(&sharers); t; t = tnext) { tnext = LIST_NEXT(t,list); D3D_INFO(7, "(Rast) Adding RampMaterial(%08x) as sharer of RampMaterial(%08x)", t, new_owner); LIST_INSERT_ROOT(&new_owner->sharers, t, list); } } else { D3D_INFO(7, "(Rast) Freeing Ramp(%08x) for RampMaterial(%08x)", ramp, this);
/* * XXX maybe we should donate the ramp to a material * which is sharing the ramp of a material which does not * match its own colors. * * Set the contents of the ramp to black, which will * possibly help out some lower level color allocation. */ int i; RLDDIColormap* cmap = driver->rampmap->cmap;
for (i = 0; i < ramp->size; i++) cmap->set_color(cmap, ramp->base + i, 0, 0, 0);
RLDDIRampmapFree(driver->rampmap, ramp); } }
ramp = NULL; }
void RampMaterial::SetColorsStd() { int base = ramp->base; int size = ramp->size; int dsize; int ssize; int i, specular; float ambient = (float) VALTOD(this->ambient); RLDDIColormap* cmap = driver->rampmap->cmap;
if ((size <= 2) || ((mat.specular.r == 0.0) && (mat.specular.g == 0.0) && (mat.specular.b == 0.0))) specular = FALSE; else specular = TRUE;
if (ramp->size == 1) { cmap->set_color(cmap, base, (int)(255.0 * mat.diffuse.r), (int)(255.0 * mat.diffuse.g), (int)(255.0 * mat.diffuse.b)); return; }
if (specular != 0) { dsize = (3 * ramp->size) / 4; ssize = ramp->size / 4; } else { dsize = ramp->size; ssize = 0; } for (i = 0; i < dsize; i++) { float intensity = (1 - ambient) * ((float)i / (dsize - 1)); float r = (mat.emissive.r + ambient * mat.ambient.r + intensity * mat.diffuse.r); float g = (mat.emissive.g + ambient * mat.ambient.g + intensity * mat.diffuse.g); float b = (mat.emissive.b + ambient * mat.ambient.b + intensity * mat.diffuse.b); if (r > 1.0) r = (float)1.0; if (g > 1.0) g = (float)1.0; if (b > 1.0) b = (float)1.0; cmap->set_color(cmap, base + i, (int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b)); } if (ssize) { float mdr, mdg, mdb; /* Maximum diffuse values */ float sr, sg, sb;
mdr = (mat.emissive.r + ambient * mat.ambient.r + (1 - ambient) * mat.diffuse.r); mdg = (mat.emissive.g + ambient * mat.ambient.g + (1 - ambient) * mat.diffuse.g); mdb = (mat.emissive.b + ambient * mat.ambient.b + (1 - ambient) * mat.diffuse.b);
if (mdr > 1.0) mdr = (float)1.0; if (mdg > 1.0) mdg = (float)1.0; if (mdb > 1.0) mdb = (float)1.0;
sr = mdr + mat.specular.r; sg = mdg + mat.specular.g; sb = mdb + mat.specular.b;
if (sr > 1.0) sr = (float)1.0; if (sg > 1.0) sg = (float)1.0; if (sb > 1.0) sb = (float)1.0;
for (i = 0; i < ssize; i++) { float s = (float)i / (ssize - 1); float r = (1 - s) * mdr + s * sr; float g = (1 - s) * mdg + s * sg; float b = (1 - s) * mdb + s * sb; cmap->set_color(cmap, base + dsize + i, (int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b)); } } }
void RampMaterial::SetColorsFog() { int base = ramp->base; int size = ramp->size; int dsize; int ssize; int i, specular; float ambient = (float) VALTOD(this->ambient); RLDDIColormap* cmap = driver->rampmap->cmap; float fr, fg, fb;
fr = RGBA_GETRED(driver->fog_color) / 255.0f; fg = RGBA_GETGREEN(driver->fog_color) / 255.0f; fb = RGBA_GETBLUE(driver->fog_color) / 255.0f;
if ((size <= 2) || ((mat.specular.r == 0.0) && (mat.specular.g == 0.0) && (mat.specular.b == 0.0))) specular = 0;
if (ramp->size == 1) { cmap->set_color(cmap, base, (int)(255.0 * mat.diffuse.r), (int)(255.0 * mat.diffuse.g), (int)(255.0 * mat.diffuse.b)); return; }
if (specular != 0) { dsize = (3 * ramp->size) / 4; ssize = ramp->size / 4; } else { dsize = ramp->size; ssize = 0; } for (i = 0; i < dsize; i++) { float intensity = (1 - ambient) * ((float)i / (dsize - 1)); float r = (mat.emissive.r + ambient * mat.ambient.r + intensity * mat.diffuse.r); float g = (mat.emissive.g + ambient * mat.ambient.g + intensity * mat.diffuse.g); float b = (mat.emissive.b + ambient * mat.ambient.b + intensity * mat.diffuse.b); r += (1.0f - intensity) * fr; g += (1.0f - intensity) * fg; b += (1.0f - intensity) * fb; if (r > 1.0) r = (float)1.0; if (g > 1.0) g = (float)1.0; if (b > 1.0) b = (float)1.0; cmap->set_color(cmap, base + i, (int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b)); } if (ssize) { float mdr, mdg, mdb; /* Maximum diffuse values */ float sr, sg, sb;
mdr = (mat.emissive.r + ambient * mat.ambient.r + (1 - ambient) * mat.diffuse.r); mdg = (mat.emissive.g + ambient * mat.ambient.g + (1 - ambient) * mat.diffuse.g); mdb = (mat.emissive.b + ambient * mat.ambient.b + (1 - ambient) * mat.diffuse.b);
if (mdr > 1.0) mdr = (float)1.0; if (mdg > 1.0) mdg = (float)1.0; if (mdb > 1.0) mdb = (float)1.0;
sr = mdr + mat.specular.r; sg = mdg + mat.specular.g; sb = mdb + mat.specular.b;
if (sr > 1.0) sr = (float)1.0; if (sg > 1.0) sg = (float)1.0; if (sb > 1.0) sb = (float)1.0;
for (i = 0; i < ssize; i++) { float s = (float)i / (ssize - 1); float r = (1 - s) * mdr + s * sr; float g = (1 - s) * mdg + s * sg; float b = (1 - s) * mdb + s * sb; cmap->set_color(cmap, base + dsize + i, (int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b)); } } }
void RampMaterial::SetColors() { if (!LIST_ORPHAN_MEMBER(this, deferredlist)) { LIST_DELETE(this, deferredlist); }
D3D_INFO(7, "(Rast) Setting colors for RampMaterial(%08x)", this); if (fog_enable) SetColorsFog(); else SetColorsStd(); }
//----------------------------------------------------------------------------- // // RLDDIRampBeginSceneHook // // Called at clear time to advance material ages and process deferred color // setting. Also deletes orphaned IntMaterials. // //----------------------------------------------------------------------------- void RLDDIRampBeginSceneHook(RLDDIRampLightingDriver* driver) { AgeList* oldest;
if (driver->already_aged) return; driver->already_aged = TRUE;
D3D_INFO(6, "(Rast) Aging materials in Clear");
/* * remove the oldest list and make that the new age=0 list. */ oldest = CIRCLE_QUEUE_LAST(&driver->agequeue); DDASSERT(LIST_FIRST(&oldest->agelist) == NULL); CIRCLE_QUEUE_DELETE(&driver->agequeue, oldest, list); CIRCLE_QUEUE_INSERT_ROOT(&driver->agequeue, AgeList, oldest, list); driver->active = oldest; D3D_INFO(7, "(Rast) New active list is %08x", driver->active);
/* * Set the colors of any ramp materials which inherited color * resources last frame. */ for (RampMaterial* rm = LIST_FIRST(&driver->rmdeferred); rm; rm = LIST_FIRST(&driver->rmdeferred)) { D3D_INFO(6, "(Rast) Processing deferred SetColor for RampMaterial(%08x)", rm); rm->SetColors(); }
/* * Any internal materials on the orphans list lost their parents last * frame. If they are inactive, reclaim them here instead of waiting * for them to die of old age. */ IntMaterial* intmat; IntMaterial* intmat_next; for (intmat = LIST_FIRST(&driver->orphans); intmat; intmat = intmat_next) { intmat_next = LIST_NEXT(intmat,list); if (!intmat->IsActive()) { D3D_INFO(9, "(Rast) Destroying inactive orphan IntMaterial(%08x)", intmat); delete intmat; } } }
//----------------------------------------------------------------------------- // // RLDDIRampEndSceneHook // // Called at update time to reclaim unused color resources and reclaim // memory for old IntMaterials. // // The age1 list will contain materials which were active last frame // and have not been used since the last Clear. // We remove their colour resources. // // The agemax list will contain inactive materials which have not // been used for AGE_MAX-1 frames. These are obsolete and we reclaim // their memory. // // NOT CALLING THIS CONSTITUTES A MEMORY LEAK. // //----------------------------------------------------------------------------- void RLDDIRampEndSceneHook(RLDDIRampLightingDriver* driver) { AgeList* age1 = CIRCLE_QUEUE_NEXT(&driver->agequeue,driver->active,list); AgeList* agemax = CIRCLE_QUEUE_LAST(&driver->agequeue); IntMaterial* intmat;
driver->already_aged = FALSE;
D3D_INFO(9, "(Rast) Processing materials in Update");
/* * The age1 list will contain materials which were active last frame * and have not been used since the last Clear. * We remove their colour resources. */ D3D_INFO(7, "(Rast) Deactivating any materials on old active list %08x", age1); for (intmat = LIST_FIRST(&age1->agelist); intmat; intmat = LIST_NEXT(intmat,agelist)) { D3D_INFO(6, "(Rast) IntMaterial(%08x) not used this frame, deactivating", intmat); intmat->Deactivate(); }
/* * The agemax list will contain inactive materials which have not * been used for AGE_MAX-1 frames. These are obsolete and we reclaim * their memory. */ for (intmat = LIST_FIRST(&agemax->agelist); intmat; // this seems wierd, but I think it is O.K. since IntMaterial's destructor // removes itself from the agelist intmat = LIST_FIRST(&agemax->agelist)) { D3D_INFO(6, "(Rast) IntMaterial(%08x) dying of old age", intmat); delete intmat; } }
inline ExtMaterial* MaterialHandleLookup(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat) { DDASSERT(hMat); return (ExtMaterial*)((((D3DFE_MATERIAL*)ULongToPtr(hMat))->pRmMat)); }
//----------------------------------------------------------------------------- // // RLDDIRampMaterialChanged // // Called when the contents of D3DMATERIAL we have already made a ExtMaterial // for changes. // //----------------------------------------------------------------------------- long RLDDIRampMaterialChanged(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat) { D3DMATERIAL* lpMat = &((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat; ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
// Don't know if MaterialChanged is supposed to unconditionally set the current // material or not. In any case, this code seems to make the uvis RM test app // work if (NULL == driver->current_material) { driver->current_material = extmat; }
extmat->SetMaterial(lpMat); return DD_OK; }
//----------------------------------------------------------------------------- // // RLDDIRampSetMaterial // // Called when a D3DLIGHTSTATE_MATERIAL changes, which sets the // driver->current_material. // //----------------------------------------------------------------------------- long RLDDIRampSetMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat)
{ if (hMat == NULL) { // NULL material is legal driver->current_material = NULL; return D3D_OK; } ExtMaterial* extmat = MaterialHandleLookup(driver, hMat); driver->current_material = extmat;
// D3DMATERIALHANDLE hMat = (D3DMATERIALHANDLE)arg; // ExtMaterial* extmat; // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*)drv; // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)drv; // LPRLDDIGENRASDRIVER rasDrv = (LPRLDDIGENRASDRIVER)drv->next; // // if (!extmat) { // return DDERR_NOTFOUND; // } // // if (extmat->GetMaterial()->power > 0) { // SpecularTable* spec; // // for (spec = LIST_FIRST(&driver->specular_tables) // ; // intentionally left blank // spec; // spec = LIST_NEXT(spec,list)) { // if (spec->power == extmat->GetMaterial()->power) // break; // } // if (spec == NULL) { // spec = CreateSpecularTable(extmat->GetMaterial()->power); // if (spec == NULL) // return DDERR_OUTOFMEMORY; // LIST_INSERT_ROOT(&driver->specular_tables, spec, list); // } // driver->specular_table = spec; // } else { // driver->specular_table = NULL; // } // // sdriver->hMat = hMat; // // if (rasDrv->driver.lpD3DDevI->rstates[D3DRENDERSTATE_TEXTUREHANDLE] != extmat->GetMaterial()->hTexture) // rasDrv->badRampTex = 1; /* Currently hTex are not matched */ // else // rasDrv->badRampTex = 0;
return DD_OK; }
//----------------------------------------------------------------------------- // // RLDDIRampCreateMaterial // // Called to create a new ExtMaterial for a given D3DFE_MATERIAL. // //----------------------------------------------------------------------------- long RLDDIRampCreateMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat, PD3DI_RASTCTX pCtx) { D3DMATERIAL* lpMat = &((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat; ExtMaterial* extmat;
driver->fog_enable = pCtx->pdwRenderState[D3DRENDERSTATE_FOGENABLE]; driver->fog_color = pCtx->pdwRenderState[D3DRENDERSTATE_FOGCOLOR];
extmat = new ExtMaterial(driver, hMat); if (extmat == NULL) return (long) NULL;
LIST_INSERT_ROOT(&driver->materials, extmat, list);
extmat->SetMaterial(lpMat);
((D3DFE_MATERIAL*)ULongToPtr(hMat))->pRmMat = (LPVOID)extmat;
return DD_OK; }
//----------------------------------------------------------------------------- // // RLDDIRampDestroyMaterial // // Called to delete a ExtMaterial and all associated underlying memory and rampmap // allocations for a given D3DFE_MATERIAL. // //----------------------------------------------------------------------------- long RLDDIRampDestroyMaterial(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat) { ExtMaterial* extmat = MaterialHandleLookup(driver, hMat);
// take this element off the list before deleting it, so driver->materials // gets updated when it should LIST_DELETE(extmat, list);
delete extmat; return DD_OK; }
static long LookupMaterial(RLDDIRampLightingDriver* driver, RLDDILookupMaterialData* data) { ExtMaterial* extmat = (ExtMaterial*) ULongToPtr(data->hMat); unsigned long* texture_colors; BOOL specular; HRESULT error;
if ((error = extmat->FindLightingRange(&data->base, &data->size, &specular, &texture_colors)) != DD_OK) return error;
return DD_OK; }
//----------------------------------------------------------------------------- // // RLDDIRampMaterialToPixel // // Call to convert a previously created material to a color for use in clearing // the color buffer, for example. // //----------------------------------------------------------------------------- unsigned long RLDDIRampMaterialToPixel(RLDDIRampLightingDriver* driver, D3DMATERIALHANDLE hMat) { ExtMaterial* extmat = MaterialHandleLookup(driver, hMat); RLDDILookupMaterialData data;
data.hMat = (D3DMATERIALHANDLE)((ULONG_PTR)extmat);
LookupMaterial(driver, &data);
return driver->pixelmap[data.base]; }
//----------------------------------------------------------------------------- // // RLDDIRampMakePaletteRGB8 // // Call to set up the RGB8 palette and rampmap. This is a palette of 216 (== 6**3) // entries of 6 gradations each for r, g, b. Using this palette requires // multiplies by 6. // //----------------------------------------------------------------------------- long RLDDIRampMakePaletteRGB8(RLDDIRampLightingDriver* driver) { RLDDIColormap* cmap = driver->rampmap->cmap;
int r, g, b; int i = 0;
for (r = 0; r < 6; r++) { for (g = 0; g < 6; g++) { for (b = 0; b < 6; b++) { cmap->set_color(cmap, i, (int)((255.0/5.0) * r), (int)((255.0/5.0) * g), (int)((255.0/5.0) * b)); i++; } } } return DD_OK; }
long RLDDIRampPaletteChanged(RLDDIRampLightingDriver* driver, D3DTEXTUREHANDLE hTex) { PD3DI_SPANTEX tex;
#ifdef DEBUG __try { #endif tex = HANDLE_TO_SPANTEX(hTex); tex->iGeneration++; LPDDRAWI_DDRAWSURFACE_LCL pLcl = ((LPDDRAWI_DDRAWSURFACE_INT) tex->pSurf[0])->lpLcl; // Palette might be changed if (tex->Format == D3DI_SPTFMT_PALETTE8 || tex->Format == D3DI_SPTFMT_PALETTE4) { if (pLcl->lpDDPalette) { LPDDRAWI_DDRAWPALETTE_GBL pPal = pLcl->lpDDPalette->lpLcl->lpGbl; tex->pPalette = (PUINT32)pPal->lpColorTable; } } #ifdef DEBUG } __except (EXCEPTION_EXECUTE_HANDLER) { D3D_ERR("Invalid texture handle"); } #endif
return DD_OK; }
//static long RampLightingService(RLDDIDriver* drv, RLDDIServiceType type, // long arg1, void* arg2) //{ // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv; // RLDDISoftLightingDriver* sdriver = (RLDDISoftLightingDriver*)driver; // D3DLIGHTDATA* data; // int mustService = FALSE; // HRESULT err = DDERR_NOTFOUND; // // /* // * Handle any services which we recognise. // */ // switch (type) { // case RLDDIPush: // { RLDDIServiceProc *table = (RLDDIServiceProc *) arg2; // // drv->data->lighting = drv; // if ((err = drv->service(drv, RLDDIFindRampmap, 0, &driver->rampmap)) != D3D_OK) // return err; // table[RLDDIPush] = RampLightingService; // table[RLDDIPop] = RampLightingService; // table[RLDDIApplyMaterialsUnlit] = serviceUnlight; // table[RLDDIApplyMaterialsLit] = RampLightingService; // table[RLDDIApplyMaterialShade] = ApplyMaterialShade; // table[RLDDISetFogMode] = RampLightingService; // table[RLDDISetFogStart] = RampLightingService; // table[RLDDISetFogEnd] = RampLightingService; // table[RLDDISetFogDensity] = RampLightingService; // table[RLDDISetFogColor] = RampLightingService; // table[RLDDISetLight] = RampLightingService; // table[RLDDISetAmbientLight] = RampLightingService; // table[RLDDILookupMaterial] = RampLightingService; // table[RLDDISetViewport] = RampLightingService; // table[RLDDISetMaterial] = SetMaterial; // table[RLDDICreateMaterial] = RampLightingService; // table[RLDDIDestroyMaterial] = RampLightingService; // table[RLDDIFindMaterial] = RampLightingService; // table[RLDDIMaterialChanged] = RampLightingService; // table[RLDDISceneCapture] = RampLightingService; // table[RLDDIClear] = RampLightingService; // table[RLDDIClearZ] = RampLightingService; // table[RLDDIClearBoth] = RampLightingService; // } // return DD_OK; // // case RLDDIPop: // ReclaimMaterials(driver); // drv->service(drv, RLDDIReleaseRampmap, 0, driver->rampmap); // return DD_OK; // // case RLDDIApplyMaterialsUnlit: // return serviceUnlight(drv, type, arg1, arg2); // // case RLDDIApplyMaterialsLit: // data = (LPD3DLIGHTDATA) arg2; // if (driver->current_material == NULL) // return DD_OK; // if (driver->current_material->GetMaterial()->dwRampSize == 1) { // serviceUnlight(drv, type, arg1, arg2); // return DD_OK; // } // if (sdriver->count == 1 // && (sdriver->lights->type == RLLightDirectional // || sdriver->lights->type == RLLightParallelPoint) // && sdriver->lights->shade > 0 // && sdriver->lights->shade <= ITOVALP(1, 8) // && !driver->fog_enable && sdriver->lights->version==1) // if (driver->specular_table) // return Light1DirectionalS(driver, arg1, (LPD3DLIGHTDATA)arg2); // else // return Light1Directional(driver, arg1, (LPD3DLIGHTDATA)arg2); // else // if (driver->specular_table) // return LightS(driver, arg1, (LPD3DLIGHTDATA)arg2); // else // return Light(driver, arg1, (LPD3DLIGHTDATA)arg2); // break; // // case RLDDISetLight: // { // D3DI_LIGHT* newLights; // // if (arg1 > sdriver->count - 1) { // if ((err = D3DMalloc((void**)&newLights, // (arg1 + 1) * sizeof(D3DI_LIGHT))) != DD_OK) { // return err; // } // memset(newLights, 0, (arg1 + 1) * sizeof(D3DI_LIGHT)); // memcpy(newLights, sdriver->lights, sdriver->count * sizeof(D3DI_LIGHT)); // if (sdriver->lights) { // D3DFree(sdriver->lights); // } // sdriver->lights = newLights; // sdriver->count = arg1 + 1; // } // } // memcpy(&sdriver->lights[arg1], arg2, sizeof(D3DI_LIGHT)); // // /* // * The light vectors could be out of date. // */ // ((RLDDITransformDriver*)drv->data->transform)->age_world = 1; // // return DD_OK; // // case RLDDISetFogMode: // { // D3DFOGMODE* fog = (D3DFOGMODE*) arg2; // sdriver->fog_mode = *fog; // driver->fog_enable = sdriver->fog_mode != D3DFOG_NONE; // // break; // } // // case RLDDISetFogStart: // { // float* fog = (float*) arg2; // sdriver->fog_start = *fog; // // break; // } // case RLDDISetFogEnd: // { // float* fog = (float*) arg2; // sdriver->fog_end = *fog; // // break; // } // case RLDDISetFogDensity: // { // float* fog = (float*) arg2; // sdriver->fog_density = *fog; // // break; // } // // case RLDDISetFogColor: // { // driver->fog_color = arg1; // break; // } // // case RLDDIClear: // case RLDDIClearZ: // case RLDDIClearBoth: // BeginSceneHook(driver); // goto chain; // // case RLDDISceneCapture: // if (arg1) // BeginSceneHook(driver); // else // EndSceneHook(driver); // goto chain; // // case RLDDISetAmbientLight: // sdriver->ambient = INCPREC(FX8TOVAL((unsigned long) arg1 >> 24), 8); // sdriver->ambient_save = arg1; // break; // // case RLDDIApplyMaterialShade: // return ApplyMaterialShade(drv, type, arg1, arg2); // // case RLDDILookupMaterial: // return LookupMaterial(driver, (RLDDILookupMaterialData*) arg2); // // case RLDDISetMaterial: // return SetMaterial(drv, type, arg1, arg2); // // case RLDDICreateMaterial: // return CreateMaterial(driver, (LPD3DMATERIALHANDLE)arg1, (LPD3DMATERIAL)arg2); // // case RLDDIDestroyMaterial: // return DestroyMaterial(driver, (D3DMATERIALHANDLE)arg1); // // case RLDDIFindMaterial: // { // LPD3DMATERIAL* lplpMat = (LPD3DMATERIAL*)arg2; // ExtMaterial* extmat = (ExtMaterial*)arg1; // // *lplpMat = extmat->GetMaterial(); // } // return DD_OK; // // case RLDDIMaterialChanged: // { // ExtMaterial* extmat = (ExtMaterial*)arg1; // // extmat->SetMaterial((LPD3DMATERIAL) arg2); // // return DD_OK; // } // // case RLDDISetViewport: // driver->viewport_id = arg1; // /* // * Chain to the next driver. // */ // if (drv->next) // return drv->next->service(drv->next, type, arg1, arg2); // return DD_OK; // // default: chain: // mustService = TRUE; // } // // if (drv->next) // err = (HRESULT) drv->next->service(drv->next, type, arg1, arg2); // // return (mustService || err != DDERR_NOTFOUND)? err : DD_OK; //} // //unsigned long* RLDDIRampFindTexturePixels(RLDDIDriver* drv, D3DMATERIALHANDLE hMat) //{ // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv; // ExtMaterial* extmat = (ExtMaterial*) hMat; // PD3DI_SPANTEX tex = HANDLE_TO_SPANTEX(extmat->GetMaterial()->hTexture); // unsigned long base, size; // unsigned long* texture_colors; // HRESULT error; // // if (!tex) { // return NULL; // } // driver = (RLDDIRampLightingDriver*) tex->owner; // // if (extmat == NULL) // return NULL; // if ((error = extmat->FindLightingRange(&base, &size, &texture_colors)) != DD_OK) // return NULL; // // return texture_colors; //} // //void*GetMaterialTextureHandle(RLDDIDriver* drv) //{ // RLDDIRampLightingDriver* driver = (RLDDIRampLightingDriver*) drv; // ExtMaterial* extmat = driver->current_material; // PD3DI_SPANTEX tex = NULL; // if(extmat){ // LPD3DMATERIAL mat = extmat->GetMaterial(); // if (mat && mat->hTexture) // tex = HANDLE_TO_SPANTEX(mat->hTexture); // } // // return tex; //}
define(`d_Ramp_ScaleImage', ` dnl define(`d_BPP', eval($1/8))dnl define(`d_Type', ifelse($1, 8, `UINT8', $1, 16, `UINT16', $1, 24, `UINT8', $1, 32, `UINT32'))dnl dnl void Ramp_Mono_ScaleImage_$1(PD3DI_RASTCTX pCtx, D3DMATERIALHANDLE hMat, LPD3DRECT pRect) { RLDDIRampLightingDriver *pLtDriver = (RLDDIRampLightingDriver*)pCtx->pRampDrv;
RLDDIRampSetMaterial(pLtDriver, hMat); PD3DI_SPANTEX pTex; pTex = HANDLE_TO_SPANTEX(((D3DFE_MATERIAL*)ULongToPtr(hMat))->mat.hTexture);
if (pLtDriver && pLtDriver->current_material) { DWORD dwBase; DWORD dwSize; unsigned long* pixels; unsigned long* map = (unsigned long*)pCtx->pRampMap; BOOL bSpecular;
// Update the ramp info. in RastCtx pLtDriver->current_material->FindLightingRange( &dwBase, &dwSize, &bSpecular, (unsigned long**)&pixels);
// Make sure DD Palette is updated after it gets set by FindLightingRange RLDDIRampUpdateDDPalette(pCtx);
LPDDRAWI_DDRAWSURFACE_LCL pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pTex->pSurf[0]))->lpLcl; int iTexWidth = pLcl->lpGbl->wWidth; int iTexHeight = pLcl->lpGbl->wHeight; int src_width = pLcl->lpGbl->lPitch; pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pCtx->pDDS))->lpLcl; int iSurfWidth = pLcl->lpGbl->wWidth; int iSurfHeight = pLcl->lpGbl->wHeight;
int x1 = pRect->x1; int y1 = pRect->y1; int x2 = pRect->x2; int y2 = pRect->y2; int width = x2 - x1; int height = y2 - y1; FLOAT scalex = (FLOAT)iSurfWidth/(FLOAT)iTexWidth; FLOAT scaley = (FLOAT)iSurfHeight/(FLOAT)iTexHeight; int dstx = x1; int dsty = y1;
unsigned char* src = pTex->pBits[0]; int src_skip; unsigned char* dst = pCtx->pSurfaceBits + dstx * d_BPP + dsty * pCtx->iSurfaceStride; int dst_skip = pCtx->iSurfaceStride - width * d_BPP; int i;
if ((scalex == 1.0F) && (scaley == 1.0F)) { src = src + src_width * y1 + x1; src_skip = src_width - width;
do { i = width; do { ifelse($1, 24, ` *(d_Type*)(dst+0) = ((d_Type*)(&map[pixels[*src]]))[0]; *(d_Type*)(dst+1) = ((d_Type*)(&map[pixels[*src]]))[1]; *(d_Type*)(dst+2) = ((d_Type*)(&map[pixels[*src++]]))[2];',` *(d_Type*)dst = (d_Type)map[pixels[*src++]];') dst += d_BPP; } while (--i); src += src_skip; dst += dst_skip; } while (--height); } else { FLOAT mu, mv; FLOAT u, v, u_start;
/* * Turn the scale values into deltas which we can use to * interpolate in the texture. */ mu = 1.0f/scalex; mv = 1.0f/scaley;
/* * Work out the real source address in the unscaled texture. * ~.5 offset makes the result stable for even scales which are common. */ u = ((FLOAT)x1+0.4999f) * mu; v = ((FLOAT)y1+0.4999f) * mv;
u_start = u; do { unsigned char* src_line = src + src_width * int(v);
u = u_start; i = width; do { ifelse($1, 24, ` *(d_Type*)(dst+0) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[0]; *(d_Type*)(dst+1) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[1]; *(d_Type*)(dst+2) = ((d_Type*)(&map[pixels[src_line[int(u)]]]))[2];',` *(d_Type*)dst = (d_Type)map[pixels[src_line[int(u)]]];') dst += d_BPP; u += mu; } while (--i); v += mv; dst += dst_skip; } while (--height); } } } ')dnl
d_Ramp_ScaleImage(8) d_Ramp_ScaleImage(16) d_Ramp_ScaleImage(24) d_Ramp_ScaleImage(32)
|