⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdfx_texman.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
        const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1;        int tmu;        tdfxMemRange *tmp, *next;        /* Deallocate the pool of free tdfxMemRange nodes */        tmp = shared->tmPool;        while (tmp) {            next = tmp->next;            FREE(tmp);            tmp = next;        }        /* Delete the texture memory block tdfxMemRange nodes */        for (tmu = 0; tmu < numTMUs; tmu++) {            tmp = shared->tmFree[tmu];            while (tmp) {                next = tmp->next;                FREE(tmp);                tmp = next;            }        }        FREE(shared);        fxMesa->glCtx->Shared->DriverData = NULL;    }}/* * Delete a tdfxMemRange struct. * We keep a linked list of free/available tdfxMemRange structs to * avoid extra malloc/free calls. */#if 0static voidDeleteRangeNode_NoLock(struct TdfxSharedState *shared, tdfxMemRange *range){    /* insert at head of list */    range->next = shared->tmPool;    shared->tmPool = range;}#endif#define DELETE_RANGE_NODE(shared, range) \    (range)->next = (shared)->tmPool;    \    (shared)->tmPool = (range)/* * When we've run out of texture memory we have to throw out an * existing texture to make room for the new one.  This function * determins the texture to throw out. */static struct gl_texture_object *FindOldestObject(tdfxContextPtr fxMesa, FxU32 tmu){    const GLuint bindnumber = fxMesa->texBindNumber;    struct gl_texture_object *oldestObj, *lowestPriorityObj;    GLfloat lowestPriority;    GLuint oldestAge;    GLuint id;    struct _mesa_HashTable *textures = fxMesa->glCtx->Shared->TexObjects;    oldestObj = NULL;    oldestAge = 0;    lowestPriority = 1.0F;    lowestPriorityObj = NULL;    for (id = _mesa_HashFirstEntry(textures);         id;         id = _mesa_HashNextEntry(textures, id)) {        struct gl_texture_object *obj           = _mesa_lookup_texture(fxMesa->glCtx, id);        tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj);        if (info && info->isInTM &&            ((info->whichTMU == tmu) || (info->whichTMU == TDFX_TMU_BOTH) ||             (info->whichTMU == TDFX_TMU_SPLIT))) {            GLuint age, lasttime;            assert(info->tm[0]);            lasttime = info->lastTimeUsed;            if (lasttime > bindnumber)                age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */            else                age = bindnumber - lasttime;            if (age >= oldestAge) {                oldestAge = age;                oldestObj = obj;            }            /* examine priority */            if (obj->Priority < lowestPriority) {                lowestPriority = obj->Priority;                lowestPriorityObj = obj;            }        }    }    if (lowestPriority < 1.0) {        ASSERT(lowestPriorityObj);        /*        printf("discard %d pri=%f\n", lowestPriorityObj->Name, lowestPriority);        */        return lowestPriorityObj;    }    else {        /*        printf("discard %d age=%d\n", oldestObj->Name, oldestAge);        */        return oldestObj;    }}#if 0static voidFlushTexMemory(tdfxContextPtr fxMesa){    struct _mesa_HashTable *textures = fxMesa->glCtx->Shared->TexObjects;    GLuint id;    for (id = _mesa_HashFirstEntry(textures);         id;         id = _mesa_HashNextEntry(textures, id)) {       struct gl_texture_object *obj          = _mesa_lookup_texture(fxMesa->glCtx, id);       if (obj->RefCount < 2) {          /* don't flush currently bound textures */          tdfxTMMoveOutTM_NoLock(fxMesa, obj);       }    }}#endif/* * Find the address (offset?) at which we can store a new texture. * <tmu> is the texture unit. * <size> is the texture size in bytes. */static FxU32FindStartAddr(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 size){    struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;    struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;    tdfxMemRange *prev, *block;    FxU32 result;#if 0    int discardedCount = 0;#define MAX_DISCARDS 10#endif    if (shared->umaTexMemory) {        assert(tmu == TDFX_TMU0);    }    _glthread_LOCK_MUTEX(mesaShared->Mutex);    while (1) {        prev = NULL;        block = shared->tmFree[tmu];        while (block) {            if (block->endAddr - block->startAddr >= size) {                /* The texture will fit here */                result = block->startAddr;                block->startAddr += size;                if (block->startAddr == block->endAddr) {                    /* Remove this node since it's empty */                    if (prev) {                        prev->next = block->next;                    }                    else {                        shared->tmFree[tmu] = block->next;                    }                    DELETE_RANGE_NODE(shared, block);                }                shared->freeTexMem[tmu] -= size;                _glthread_UNLOCK_MUTEX(mesaShared->Mutex);                return result;            }            prev = block;            block = block->next;        }        /* We failed to find a block large enough to accomodate <size> bytes.         * Find the oldest texObject and free it.         */#if 0        discardedCount++;        if (discardedCount > MAX_DISCARDS + 1) {            _mesa_problem(NULL, "%s: extreme texmem fragmentation", __FUNCTION__);            _glthread_UNLOCK_MUTEX(mesaShared->Mutex);            return BAD_ADDRESS;        }        else if (discardedCount > MAX_DISCARDS) {            /* texture memory is probably really fragmented, flush it */            FlushTexMemory(fxMesa);        }        else#endif        {            struct gl_texture_object *obj = FindOldestObject(fxMesa, tmu);            if (obj) {                tdfxTMMoveOutTM_NoLock(fxMesa, obj);                fxMesa->stats.texSwaps++;            }            else {                _mesa_problem(NULL, "%s: extreme texmem fragmentation", __FUNCTION__);                _glthread_UNLOCK_MUTEX(mesaShared->Mutex);                return BAD_ADDRESS;            }        }    }    /* never get here, but play it safe */    _glthread_UNLOCK_MUTEX(mesaShared->Mutex);    return BAD_ADDRESS;}/* * Remove the given tdfxMemRange node from hardware texture memory. */static voidRemoveRange_NoLock(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range){    struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;    struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;    tdfxMemRange *block, *prev;    if (shared->umaTexMemory) {       assert(tmu == TDFX_TMU0);    }    if (!range)        return;    if (range->startAddr == range->endAddr) {        DELETE_RANGE_NODE(shared, range);        return;    }    shared->freeTexMem[tmu] += range->endAddr - range->startAddr;    /* find position in linked list to insert this tdfxMemRange node */    prev = NULL;    block = shared->tmFree[tmu];    while (block) {        assert(range->startAddr != block->startAddr);        if (range->startAddr > block->startAddr) {            prev = block;            block = block->next;        }        else {            break;        }    }    /* Insert the free block, combine with adjacent blocks when possible */    range->next = block;    if (block) {        if (range->endAddr == block->startAddr) {            /* Combine */            block->startAddr = range->startAddr;            DELETE_RANGE_NODE(shared, range);            range = block;        }    }    if (prev) {        if (prev->endAddr == range->startAddr) {            /* Combine */            prev->endAddr = range->endAddr;            prev->next = range->next;            DELETE_RANGE_NODE(shared, range);        }        else {            prev->next = range;        }    }    else {        shared->tmFree[tmu] = range;    }}#if 0 /* NOT USED */static voidRemoveRange(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range){    struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;    _glthread_LOCK_MUTEX(mesaShared->Mutex);    RemoveRange_NoLock(fxMesa, tmu, range);    _glthread_UNLOCK_MUTEX(mesaShared->Mutex);}#endif/* * Allocate space for a texture image. * <tmu> is the texture unit * <texmemsize> is the number of bytes to allocate */static tdfxMemRange *AllocTexMem(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 texmemsize){    FxU32 startAddr;    startAddr = FindStartAddr(fxMesa, tmu, texmemsize);    if (startAddr == BAD_ADDRESS) {        _mesa_problem(fxMesa->glCtx, "%s returned NULL!  tmu=%d texmemsize=%d",               __FUNCTION__, (int) tmu, (int) texmemsize);        return NULL;    }    else {        tdfxMemRange *range;        range = NewRangeNode(fxMesa, startAddr, startAddr + texmemsize);        return range;    }}/* * Download (copy) the given texture data (all mipmap levels) into the * Voodoo's texture memory. * The texture memory must have already been allocated. */voidtdfxTMDownloadTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj){    tdfxTexInfo *ti;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -