Merged cleanly: indra/llkeyframewalkmotion.cpp -36e6946c96- worked around a bug in Aurora walking motion indra/llrender/llimagegl.cpp -fa8e1f033b- An llerrs here becomes an llwarns, to avoid bothering the user with non power of two dimensioned images indra/newview/llmanip.cpp, indra/newview/llmanipscale.cpp - "Changed hardcoded 256 constants and such to width functions" -a50f0008b2indra/newview/llpatchvertexarray.cpp -fa8e1f033b- Support patches of non power of two width indra/newview/llworldmap.h - conflict Conflicts: indra/llmessage/patch_code.cpp - My version cleaned up a bit of code duplication, so this was applied, within the new tags indra/llmessage/patch_code.h - b_large_patch in decode_patch_header defaults to false, indra/newview/llcloud.cpp patch removed. indra/llmessage/patch_dct.h - false positive indra/newview/llagent.cpp - false positive indra/newview/llfloaterregioninfo.cpp - nonsl wacky textures support meets the refactor. indra/newview/llfloaterworldmap.cpp - false positive indra/newview/llglsandbox.cpp - false positive indra/newview/llnetmap.cpp - small changes for type consistency brought into FS' patch, nothing important; also adds change to LLNetMap:draw removing getRegionWidthInMeters to keep using the constant REGION_WIDTH indra/newview/llpanelobject.cpp - Get the region width of the object we're editing for maximum pasted x/y coords indra/newview/llstartup.cpp - [Fixes old issues] My old patch did not fully use first_sim_size_x here, this has been fixed. The unused first_sim_size_y has been removed. indra/newview/llsurface.cpp - rebuildWater isn't used, removed for now. Styling conflicts otherwise. indra/newview/llsurfacepatch.cpp - remove FS patch that comments out code that isn't even in the modern source; cleaned up a mess of tags with more clear explanation, perhaps it can be expanded upon though. Some styling conflicts. indra/newview/llviewermessage.cpp - Fix the problem? setRegionWidth by number. indra/newview/llviewerobject.cpp - false positive indra/newview/llviewerparcelmgr.cpp - just styling conflicts indra/newview/llviewerparcelmgr.h - false positive indra/newview/llviewerparceloverlay.cpp - false positive indra/newview/llviewerparceloverlay.h - false positive indra/newview/llviewerregion.cpp - cleaned up LLViewerRegion::getCompositionXY patches, they're more in the way than they're worth; removed DispatchOpenRegionSettings capability mention for now, it's not related to variable regions. Also remove rebuildWater, it's not used right now. indra/newview/llvowater.cpp - false positive indra/newview/llwind.cpp - remove decode_patch_header patches for false, since we have a default; otherwise false positive. indra/newview/llworld.* - [Fixes old issues] Remove setRegionWidth by LLMessageSystem as the messages used are not always the same, the by number one remains of course. - Retained separation of connecting neighbors through the old method when the width is 256 - updateLimits() would never have been merged in, we have an entirely different grid manager, therefore it's removed. - Fix the stupidity passed on over the years wherein a static constant variable would hold the same value as the first call to setLandFarClip.. indra/newview/llworldmap.cpp -36e6946c96Aurora map workaround stuffs, parts removed; rework of LLWorldMap::simInfoFromHandle indra/newview/llworldmap.h - Cleaned up organization, avoid making members public, and fixed tagging
430 lines
8.8 KiB
C++
430 lines
8.8 KiB
C++
/**
|
|
* @file patch_code.cpp
|
|
* @brief Encode patch DCT data into bitcode.
|
|
*
|
|
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
|
|
#include "llmath.h"
|
|
//#include "vmath.h"
|
|
#include "v3math.h"
|
|
#include "patch_dct.h"
|
|
#include "patch_code.h"
|
|
#include "bitpack.h"
|
|
|
|
U32 gPatchSize, gWordBits;
|
|
|
|
void init_patch_coding(LLBitPack &bitpack)
|
|
{
|
|
bitpack.resetBitPacking();
|
|
}
|
|
|
|
void code_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
|
|
{
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *stride = (U8 *)&gopp->stride;
|
|
bitpack.bitPack(&(stride[1]), 8);
|
|
bitpack.bitPack(&(stride[0]), 8);
|
|
#else
|
|
bitpack.bitPack((U8 *)&gopp->stride, 16);
|
|
#endif
|
|
bitpack.bitPack((U8 *)&gopp->patch_size, 8);
|
|
bitpack.bitPack((U8 *)&gopp->layer_type, 8);
|
|
|
|
gPatchSize = gopp->patch_size;
|
|
}
|
|
|
|
void code_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, S32 *patch)
|
|
{
|
|
S32 i, j, temp, patch_size = gPatchSize, wbits = (ph->quant_wbits & 0xf) + 2;
|
|
U32 max_wbits = wbits + 5, min_wbits = wbits>>1;
|
|
|
|
wbits = min_wbits;
|
|
|
|
for (i = 0; i < (int) patch_size*patch_size; i++)
|
|
{
|
|
temp = patch[i];
|
|
if (temp)
|
|
{
|
|
if (temp < 0)
|
|
temp *= -1;
|
|
for (j = max_wbits; j > (int) min_wbits; j--)
|
|
{
|
|
if (temp & (1<<j))
|
|
{
|
|
if (j > wbits)
|
|
wbits = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
wbits += 1;
|
|
|
|
ph->quant_wbits &= 0xf0;
|
|
|
|
if ( (wbits > 17)
|
|
||(wbits < 2))
|
|
{
|
|
llerrs << "Bits needed per word in code_patch_header out of legal range. Adjust compression quatization." << llendl;
|
|
}
|
|
|
|
ph->quant_wbits |= (wbits - 2);
|
|
|
|
bitpack.bitPack((U8 *)&ph->quant_wbits, 8);
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *offset = (U8 *)&ph->dc_offset;
|
|
bitpack.bitPack(&(offset[3]), 8);
|
|
bitpack.bitPack(&(offset[2]), 8);
|
|
bitpack.bitPack(&(offset[1]), 8);
|
|
bitpack.bitPack(&(offset[0]), 8);
|
|
#else
|
|
bitpack.bitPack((U8 *)&ph->dc_offset, 32);
|
|
#endif
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *range = (U8 *)&ph->range;
|
|
bitpack.bitPack(&(range[1]), 8);
|
|
bitpack.bitPack(&(range[0]), 8);
|
|
#else
|
|
bitpack.bitPack((U8 *)&ph->range, 16);
|
|
#endif
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *ids = (U8 *)&ph->patchids;
|
|
bitpack.bitPack(&(ids[1]), 8);
|
|
bitpack.bitPack(&(ids[0]), 2);
|
|
#else
|
|
bitpack.bitPack((U8 *)&ph->patchids, 10);
|
|
#endif
|
|
|
|
gWordBits = wbits;
|
|
}
|
|
|
|
void code_end_of_data(LLBitPack &bitpack)
|
|
{
|
|
bitpack.bitPack((U8 *)&END_OF_PATCHES, 8);
|
|
}
|
|
|
|
void code_patch(LLBitPack &bitpack, S32 *patch, S32 postquant)
|
|
{
|
|
S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
|
|
S32 temp;
|
|
BOOL b_eob;
|
|
|
|
if ( (postquant > patch_size*patch_size)
|
|
||(postquant < 0))
|
|
{
|
|
llerrs << "Bad postquant in code_patch!" << llendl;
|
|
}
|
|
|
|
if (postquant)
|
|
patch[patch_size*patch_size - postquant] = 0;
|
|
|
|
for (i = 0; i < patch_size*patch_size; i++)
|
|
{
|
|
b_eob = FALSE;
|
|
temp = patch[i];
|
|
if (!temp)
|
|
{
|
|
b_eob = TRUE;
|
|
for (j = i; j < patch_size*patch_size - postquant; j++)
|
|
{
|
|
if (patch[j])
|
|
{
|
|
b_eob = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (b_eob)
|
|
{
|
|
bitpack.bitPack((U8 *)&ZERO_EOB, 2);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
bitpack.bitPack((U8 *)&ZERO_CODE, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (temp < 0)
|
|
{
|
|
temp *= -1;
|
|
if (temp > (1<<wbits))
|
|
{
|
|
temp = (1<<wbits);
|
|
// printf("patch quatization exceeding allowable bits!");
|
|
}
|
|
bitpack.bitPack((U8 *)&NEGATIVE_VALUE, 3);
|
|
bitpack.bitPack((U8 *)&temp, wbits);
|
|
}
|
|
else
|
|
{
|
|
if (temp > (1<<wbits))
|
|
{
|
|
temp = (1<<wbits);
|
|
// printf("patch quatization exceeding allowable bits!");
|
|
}
|
|
bitpack.bitPack((U8 *)&POSITIVE_VALUE, 3);
|
|
bitpack.bitPack((U8 *)&temp, wbits);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void end_patch_coding(LLBitPack &bitpack)
|
|
{
|
|
bitpack.flushBitPack();
|
|
}
|
|
|
|
void init_patch_decoding(LLBitPack &bitpack)
|
|
{
|
|
bitpack.resetBitPacking();
|
|
}
|
|
|
|
void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
|
|
{
|
|
U16 retvalu16;
|
|
|
|
retvalu16 = 0;
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *ret = (U8 *)&retvalu16;
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), 8);
|
|
#else
|
|
bitpack.bitUnpack((U8 *)&retvalu16, 16);
|
|
#endif
|
|
gopp->stride = retvalu16;
|
|
|
|
U8 retvalu8 = 0;
|
|
bitpack.bitUnpack(&retvalu8, 8);
|
|
gopp->patch_size = retvalu8;
|
|
|
|
retvalu8 = 0;
|
|
bitpack.bitUnpack(&retvalu8, 8);
|
|
gopp->layer_type = retvalu8;
|
|
|
|
gPatchSize = gopp->patch_size;
|
|
}
|
|
|
|
// <FS:CR> Aurora Sim
|
|
//void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph)
|
|
void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, bool b_large_patch)
|
|
// </FS:CR> Aurora Sim
|
|
{
|
|
U8 retvalu8;
|
|
|
|
retvalu8 = 0;
|
|
bitpack.bitUnpack(&retvalu8, 8);
|
|
ph->quant_wbits = retvalu8;
|
|
|
|
if (END_OF_PATCHES == ph->quant_wbits)
|
|
{
|
|
// End of data, blitz the rest.
|
|
ph->dc_offset = 0;
|
|
ph->range = 0;
|
|
ph->patchids = 0;
|
|
return;
|
|
}
|
|
|
|
U32 retvalu32 = 0;
|
|
#ifdef LL_BIG_ENDIAN
|
|
U8 *ret = (U8 *)&retvalu32;
|
|
bitpack.bitUnpack(&(ret[3]), 8);
|
|
bitpack.bitUnpack(&(ret[2]), 8);
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), 8);
|
|
#else
|
|
bitpack.bitUnpack((U8 *)&retvalu32, 32);
|
|
#endif
|
|
ph->dc_offset = *(F32 *)&retvalu32;
|
|
|
|
U16 retvalu16 = 0;
|
|
#ifdef LL_BIG_ENDIAN
|
|
ret = (U8 *)&retvalu16;
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), 8);
|
|
#else
|
|
bitpack.bitUnpack((U8 *)&retvalu16, 16);
|
|
#endif
|
|
ph->range = retvalu16;
|
|
|
|
// <FS:CR> Aurora Sim
|
|
//retvalu16 = 0;
|
|
retvalu32 = 0;
|
|
#ifdef LL_BIG_ENDIAN
|
|
//ret = (U8 *)&retvalu16;
|
|
ret = (U8*)&retvalu32;
|
|
// </FS:CR> Aurora Sim
|
|
if (b_large_patch)
|
|
{
|
|
bitpack.bitUnpack(&(ret[3]), 8);
|
|
bitpack.bitUnpack(&(ret[2]), 8);
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), 8);
|
|
}
|
|
else
|
|
{
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), 2);
|
|
}
|
|
#else
|
|
// <FS:CR> Aurora Sim
|
|
//bitpack.bitUnpack((U8 *)&retvalu16, 10);
|
|
bitpack.bitUnpack((U8*)&retvalu32, b_large_patch ? 32 : 10);
|
|
#endif
|
|
//ph->patchids = retvalu16;
|
|
ph->patchids = retvalu32;
|
|
// </FS:CR> Aurora Sim
|
|
|
|
gWordBits = (ph->quant_wbits & 0xf) + 2;
|
|
}
|
|
|
|
void decode_patch(LLBitPack &bitpack, S32 *patches)
|
|
{
|
|
#ifdef LL_BIG_ENDIAN
|
|
S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
|
|
U8 tempu8;
|
|
U16 tempu16;
|
|
U32 tempu32;
|
|
for (i = 0; i < patch_size*patch_size; i++)
|
|
{
|
|
bitpack.bitUnpack((U8 *)&tempu8, 1);
|
|
if (tempu8)
|
|
{
|
|
// either 0 EOB or Value
|
|
bitpack.bitUnpack((U8 *)&tempu8, 1);
|
|
if (tempu8)
|
|
{
|
|
// value
|
|
bitpack.bitUnpack((U8 *)&tempu8, 1);
|
|
if (tempu8)
|
|
{
|
|
// negative
|
|
patches[i] = -1;
|
|
}
|
|
else
|
|
{
|
|
// positive
|
|
patches[i] = 1;
|
|
}
|
|
if (wbits <= 8)
|
|
{
|
|
bitpack.bitUnpack((U8 *)&tempu8, wbits);
|
|
patches[i] *= tempu8;
|
|
}
|
|
else if (wbits <= 16)
|
|
{
|
|
tempu16 = 0;
|
|
U8 *ret = (U8 *)&tempu16;
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), wbits - 8);
|
|
patches[i] *= tempu16;
|
|
}
|
|
else if (wbits <= 24)
|
|
{
|
|
tempu32 = 0;
|
|
U8 *ret = (U8 *)&tempu32;
|
|
bitpack.bitUnpack(&(ret[2]), 8);
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), wbits - 16);
|
|
patches[i] *= tempu32;
|
|
}
|
|
else if (wbits <= 32)
|
|
{
|
|
tempu32 = 0;
|
|
U8 *ret = (U8 *)&tempu32;
|
|
bitpack.bitUnpack(&(ret[3]), 8);
|
|
bitpack.bitUnpack(&(ret[2]), 8);
|
|
bitpack.bitUnpack(&(ret[1]), 8);
|
|
bitpack.bitUnpack(&(ret[0]), wbits - 24);
|
|
patches[i] *= tempu32;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = i; j < patch_size*patch_size; j++)
|
|
{
|
|
patches[j] = 0;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
patches[i] = 0;
|
|
}
|
|
}
|
|
#else
|
|
S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
|
|
U32 temp;
|
|
for (i = 0; i < patch_size*patch_size; i++)
|
|
{
|
|
temp = 0;
|
|
bitpack.bitUnpack((U8 *)&temp, 1);
|
|
if (temp)
|
|
{
|
|
// either 0 EOB or Value
|
|
temp = 0;
|
|
bitpack.bitUnpack((U8 *)&temp, 1);
|
|
if (temp)
|
|
{
|
|
// value
|
|
temp = 0;
|
|
bitpack.bitUnpack((U8 *)&temp, 1);
|
|
if (temp)
|
|
{
|
|
// negative
|
|
temp = 0;
|
|
bitpack.bitUnpack((U8 *)&temp, wbits);
|
|
patches[i] = temp;
|
|
patches[i] *= -1;
|
|
}
|
|
else
|
|
{
|
|
// positive
|
|
temp = 0;
|
|
bitpack.bitUnpack((U8 *)&temp, wbits);
|
|
patches[i] = temp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = i; j < patch_size*patch_size; j++)
|
|
{
|
|
patches[j] = 0;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
patches[i] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|