/** * @brief Reorders all surfaces arrays for the specified model, grouping the surface * pointers by texture. This dramatically reduces glBindTexture calls. */ static void R_SortSurfacesArrays (const model_t *mod) { const mBspSurface_t *surf, *s; int i, ns; /* resolve the start surface and total surface count */ if (mod->type == mod_bsp) { /* world model */ s = mod->bsp.surfaces; ns = mod->bsp.numsurfaces; } else { /* submodels */ s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface]; ns = mod->bsp.nummodelsurfaces; } OBJZERO(r_sorted_surfaces); /* allocate the per-texture surfaces arrays and determine counts */ for (i = 0, surf = s; i < ns; i++, surf++) { mBspSurfaces_t *surfs = r_sorted_surfaces[surf->texinfo->image->texnum]; if (!surfs) { /* allocate it */ surfs = (mBspSurfaces_t *)Mem_PoolAlloc(sizeof(*surfs), vid_modelPool, 0); r_sorted_surfaces[surf->texinfo->image->texnum] = surfs; } surfs->count++; } /* allocate the surfaces pointers based on counts */ for (i = 0; i < r_numImages; i++) { mBspSurfaces_t *surfs = r_sorted_surfaces[r_images[i].texnum]; if (surfs) { surfs->surfaces = (mBspSurface_t **)Mem_PoolAlloc(sizeof(mBspSurface_t *) * surfs->count, vid_modelPool, 0); surfs->count = 0; } } /* sort the model's surfaces arrays into the per-texture arrays */ for (i = 0; i < NUM_SURFACES_ARRAYS; i++) { if (mod->bsp.sorted_surfaces[i]->count) { R_SortSurfacesArrays_(mod->bsp.sorted_surfaces[i]); Com_DPrintf(DEBUG_RENDERER, "%i: #%i surfaces\n", i, mod->bsp.sorted_surfaces[i]->count); } } /* free the per-texture surfaces arrays */ for (i = 0; i < r_numImages; i++) { mBspSurfaces_t *surfs = r_sorted_surfaces[r_images[i].texnum]; if (surfs) { if (surfs->surfaces) Mem_Free(surfs->surfaces); Mem_Free(surfs); } } }
/** * @brief Reorders all surfaces arrays for the specified model, grouping the surface * pointers by texture. This dramatically reduces glBindTexture calls. */ static void R_SortSurfacesArrays (const model_t *mod) { const mBspSurface_t *surf, *s; int i, ns; mBspSurfaces_t **r_sorted_surfaces = Mem_AllocTypeN(mBspSurfaces_t *, r_numImages); /* resolve the start surface and total surface count */ s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface]; ns = mod->bsp.nummodelsurfaces; /* allocate the per-texture surfaces arrays and determine counts */ for (i = 0, surf = s; i < ns; i++, surf++) { int index = R_GetImageIndex(surf->texinfo->image); mBspSurfaces_t *surfs = r_sorted_surfaces[index]; if (!surfs) { /* allocate it */ surfs = Mem_PoolAllocType(mBspSurfaces_t, vid_modelPool); r_sorted_surfaces[index] = surfs; } surfs->count++; } /* allocate the surfaces pointers based on counts */ for (i = 0; i < r_numImages; i++) { mBspSurfaces_t *surfs = r_sorted_surfaces[i]; if (surfs) { surfs->surfaces = Mem_PoolAllocTypeN(mBspSurface_t*, surfs->count, vid_modelPool); surfs->count = 0; } } /* sort the model's surfaces arrays into the per-texture arrays */ for (i = 0; i < NUM_SURFACES_ARRAYS; i++) { if (mod->bsp.sorted_surfaces[i]->count) { R_SortSurfacesArrays_(mod->bsp.sorted_surfaces[i], r_sorted_surfaces); Com_DPrintf(DEBUG_RENDERER, "%i: #%i surfaces\n", i, mod->bsp.sorted_surfaces[i]->count); } } /* free the per-texture surfaces arrays */ for (i = 0; i < r_numImages; i++) { mBspSurfaces_t *surfs = r_sorted_surfaces[i]; if (surfs) { Mem_Free(surfs->surfaces); Mem_Free(surfs); } } Mem_Free(r_sorted_surfaces); }