diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lltexlayer.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/lltexlayer.cpp')
-rw-r--r-- | linden/indra/newview/lltexlayer.cpp | 2860 |
1 files changed, 2860 insertions, 0 deletions
diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp new file mode 100644 index 0000000..0292417 --- /dev/null +++ b/linden/indra/newview/lltexlayer.cpp | |||
@@ -0,0 +1,2860 @@ | |||
1 | /** | ||
2 | * @file lltexlayer.cpp | ||
3 | * @brief A texture layer. Used for avatars. | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "imageids.h" | ||
31 | #include "llagent.h" | ||
32 | #include "llcrc.h" | ||
33 | #include "lldir.h" | ||
34 | #include "llglheaders.h" | ||
35 | #include "llimagebmp.h" | ||
36 | #include "llimagej2c.h" | ||
37 | #include "llimagetga.h" | ||
38 | #include "llpolymorph.h" | ||
39 | #include "llquantize.h" | ||
40 | #include "lltexlayer.h" | ||
41 | #include "llui.h" | ||
42 | #include "llvfile.h" | ||
43 | #include "llviewerimagelist.h" | ||
44 | #include "llviewerimagelist.h" | ||
45 | #include "llviewerstats.h" | ||
46 | #include "llviewerwindow.h" | ||
47 | #include "llvoavatar.h" | ||
48 | #include "llxmltree.h" | ||
49 | #include "pipeline.h" | ||
50 | #include "v4coloru.h" | ||
51 | #include "viewer.h" | ||
52 | |||
53 | //#include "../tools/imdebug/imdebug.h" | ||
54 | |||
55 | |||
56 | // SJB: We really always want to use the GL cache; | ||
57 | // let GL page textures in and out of video RAM instead of trying to do so by hand. | ||
58 | // const U32 USE_AVATAR_GL_CACHE_THRESHOLD = 1024 * 1024 * 35; // 35 MB | ||
59 | BOOL gUseAvatarGLCache = TRUE; //FALSE; | ||
60 | |||
61 | LLGradientPaletteList gGradientPaletteList; | ||
62 | |||
63 | // static | ||
64 | S32 LLTexLayerSetBuffer::sGLByteCount = 0; | ||
65 | S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; | ||
66 | |||
67 | //----------------------------------------------------------------------------- | ||
68 | // LLBakedUploadData() | ||
69 | //----------------------------------------------------------------------------- | ||
70 | LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ) : | ||
71 | mAvatar( avatar ), | ||
72 | mLayerSetBuffer( layerset_buffer ) | ||
73 | { | ||
74 | mID.generate(); | ||
75 | for( S32 i = 0; i < WT_COUNT; i++ ) | ||
76 | { | ||
77 | LLWearable* wearable = gAgent.getWearable( (EWearableType)i); | ||
78 | if( wearable ) | ||
79 | { | ||
80 | mWearableAssets[i] = wearable->getID(); | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | |||
85 | //----------------------------------------------------------------------------- | ||
86 | // LLTexLayerSetBuffer | ||
87 | // The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. | ||
88 | //----------------------------------------------------------------------------- | ||
89 | LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 height, BOOL has_bump ) | ||
90 | : | ||
91 | // ORDER_LAST => must render these after the hints are created. | ||
92 | LLDynamicTexture( width, height, 4, LLDynamicTexture::ORDER_LAST, TRUE ), | ||
93 | mNeedsUpdate( TRUE ), | ||
94 | mNeedsUpload( FALSE ), | ||
95 | mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates | ||
96 | mTexLayerSet( owner ), | ||
97 | mInitialized( FALSE ), | ||
98 | mBumpTexName(0) | ||
99 | { | ||
100 | LLTexLayerSetBuffer::sGLByteCount += getSize(); | ||
101 | |||
102 | if( has_bump ) | ||
103 | { | ||
104 | LLGLSUIDefault gls_ui; | ||
105 | glGenTextures(1, (GLuint*) &mBumpTexName); | ||
106 | |||
107 | LLImageGL::bindExternalTexture(mBumpTexName, 0, GL_TEXTURE_2D); | ||
108 | stop_glerror(); | ||
109 | |||
110 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
111 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
112 | |||
113 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
114 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
115 | |||
116 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||
117 | stop_glerror(); | ||
118 | |||
119 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
120 | |||
121 | LLImageGL::sGlobalTextureMemory += mWidth * mHeight * 4; | ||
122 | LLTexLayerSetBuffer::sGLBumpByteCount += mWidth * mHeight * 4; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | LLTexLayerSetBuffer::~LLTexLayerSetBuffer() | ||
127 | { | ||
128 | LLTexLayerSetBuffer::sGLByteCount -= getSize(); | ||
129 | |||
130 | if( mBumpTexName ) | ||
131 | { | ||
132 | glDeleteTextures(1, (GLuint*) &mBumpTexName); | ||
133 | stop_glerror(); | ||
134 | mBumpTexName = 0; | ||
135 | |||
136 | LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; | ||
137 | LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | // static | ||
142 | void LLTexLayerSetBuffer::dumpTotalByteCount() | ||
143 | { | ||
144 | llinfos << "Composite System GL Buffers: " << (LLTexLayerSetBuffer::sGLByteCount/1024) << "KB" << llendl; | ||
145 | llinfos << "Composite System GL Bump Buffers: " << (LLTexLayerSetBuffer::sGLBumpByteCount/1024) << "KB" << llendl; | ||
146 | } | ||
147 | |||
148 | void LLTexLayerSetBuffer::requestUpdate() | ||
149 | { | ||
150 | mNeedsUpdate = TRUE; | ||
151 | |||
152 | // If we're in the middle of uploading a baked texture, we don't care about it any more. | ||
153 | // When it's downloaded, ignore it. | ||
154 | mUploadID.setNull(); | ||
155 | } | ||
156 | |||
157 | void LLTexLayerSetBuffer::requestUpload() | ||
158 | { | ||
159 | if (!mNeedsUpload) | ||
160 | { | ||
161 | mNeedsUpload = TRUE; | ||
162 | mUploadPending = TRUE; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | void LLTexLayerSetBuffer::cancelUpload() | ||
167 | { | ||
168 | if (mNeedsUpload) | ||
169 | { | ||
170 | mNeedsUpload = FALSE; | ||
171 | } | ||
172 | mUploadPending = FALSE; | ||
173 | } | ||
174 | |||
175 | void LLTexLayerSetBuffer::pushProjection() | ||
176 | { | ||
177 | glMatrixMode(GL_PROJECTION); | ||
178 | glPushMatrix(); | ||
179 | glLoadIdentity(); | ||
180 | glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f); | ||
181 | |||
182 | glMatrixMode(GL_MODELVIEW); | ||
183 | glPushMatrix(); | ||
184 | glLoadIdentity(); | ||
185 | } | ||
186 | |||
187 | void LLTexLayerSetBuffer::popProjection() | ||
188 | { | ||
189 | glMatrixMode(GL_PROJECTION); | ||
190 | glPopMatrix(); | ||
191 | |||
192 | glMatrixMode(GL_MODELVIEW); | ||
193 | glPopMatrix(); | ||
194 | } | ||
195 | |||
196 | BOOL LLTexLayerSetBuffer::needsRender() | ||
197 | { | ||
198 | LLVOAvatar* avatar = mTexLayerSet->getAvatar(); | ||
199 | BOOL upload_now = mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal(); | ||
200 | BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; | ||
201 | if (needs_update) | ||
202 | { | ||
203 | BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatar::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); | ||
204 | if (invalid_skirt) | ||
205 | { | ||
206 | // we were trying to create a skirt texture | ||
207 | // but we're no longer wearing a skirt... | ||
208 | needs_update = FALSE; | ||
209 | cancelUpload(); | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | needs_update &= (avatar->isSelf() || (avatar->isVisible() && !avatar->isCulled())); | ||
214 | needs_update &= mTexLayerSet->isLocalTextureDataAvailable(); | ||
215 | } | ||
216 | } | ||
217 | return needs_update; | ||
218 | } | ||
219 | |||
220 | void LLTexLayerSetBuffer::preRender(BOOL clear_depth) | ||
221 | { | ||
222 | // Set up an ortho projection | ||
223 | pushProjection(); | ||
224 | |||
225 | // keep depth buffer, we don't need to clear it | ||
226 | LLDynamicTexture::preRender(FALSE); | ||
227 | } | ||
228 | |||
229 | void LLTexLayerSetBuffer::postRender(BOOL success) | ||
230 | { | ||
231 | popProjection(); | ||
232 | |||
233 | LLDynamicTexture::postRender(success); | ||
234 | } | ||
235 | |||
236 | BOOL LLTexLayerSetBuffer::render() | ||
237 | { | ||
238 | U8* baked_bump_data = NULL; | ||
239 | |||
240 | // gUseAvatarGLCache = ( gImageList.getMaxResidentTexMem() > USE_AVATAR_GL_CACHE_THRESHOLD ); | ||
241 | |||
242 | // do we need to upload, and do we have sufficient data to create an uploadable composite? | ||
243 | // When do we upload the texture if gAgent.mNumPendingQueries is non-zero? | ||
244 | BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal()); | ||
245 | BOOL success = TRUE; | ||
246 | |||
247 | // Composite bump | ||
248 | if( mBumpTexName ) | ||
249 | { | ||
250 | // Composite the bump data | ||
251 | success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight ); | ||
252 | stop_glerror(); | ||
253 | |||
254 | if (success) | ||
255 | { | ||
256 | LLGLSUIDefault gls_ui; | ||
257 | |||
258 | // read back into texture (this is done externally for the color data) | ||
259 | LLImageGL::bindExternalTexture( mBumpTexName, 0, GL_TEXTURE_2D ); | ||
260 | stop_glerror(); | ||
261 | |||
262 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight); | ||
263 | stop_glerror(); | ||
264 | |||
265 | // if we need to upload the data, read it back into a buffer | ||
266 | if( upload_now ) | ||
267 | { | ||
268 | baked_bump_data = new U8[ mWidth * mHeight * 4 ]; | ||
269 | glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data ); | ||
270 | stop_glerror(); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | // Composite the color data | ||
276 | LLGLSUIDefault gls_ui; | ||
277 | success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mWidth, mHeight ); | ||
278 | |||
279 | if( upload_now ) | ||
280 | { | ||
281 | if (!success) | ||
282 | { | ||
283 | delete baked_bump_data; | ||
284 | llinfos << "Failed attempt to bake " << mTexLayerSet->getBodyRegion() << llendl; | ||
285 | mUploadPending = FALSE; | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | readBackAndUpload(baked_bump_data); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | // reset GL state | ||
294 | glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); | ||
295 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); | ||
296 | |||
297 | // we have valid texture data now | ||
298 | mInitialized = TRUE; | ||
299 | mNeedsUpdate = FALSE; | ||
300 | |||
301 | return success; | ||
302 | } | ||
303 | |||
304 | BOOL LLTexLayerSetBuffer::updateImmediate() | ||
305 | { | ||
306 | mNeedsUpdate = TRUE; | ||
307 | BOOL result = FALSE; | ||
308 | |||
309 | if (needsRender()) | ||
310 | { | ||
311 | preRender(FALSE); | ||
312 | result = render(); | ||
313 | postRender(result); | ||
314 | } | ||
315 | |||
316 | return result; | ||
317 | } | ||
318 | |||
319 | void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) | ||
320 | { | ||
321 | // pointers for storing data to upload | ||
322 | U8* baked_color_data = new U8[ mWidth * mHeight * 4 ]; | ||
323 | |||
324 | glReadPixels(mOrigin.mX, mOrigin.mY, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_color_data ); | ||
325 | stop_glerror(); | ||
326 | |||
327 | llinfos << "Baked " << mTexLayerSet->getBodyRegion() << llendl; | ||
328 | gViewerStats->incStat(LLViewerStats::ST_TEX_BAKES); | ||
329 | |||
330 | llassert( gAgent.getAvatarObject() == mTexLayerSet->getAvatar() ); | ||
331 | |||
332 | // We won't need our caches since we're baked now. (Techically, we won't | ||
333 | // really be baked until this image is sent to the server and the Avatar | ||
334 | // Appearance message is received.) | ||
335 | mTexLayerSet->deleteCaches(); | ||
336 | |||
337 | LLGLSUIDefault gls_ui; | ||
338 | |||
339 | LLPointer<LLImageRaw> baked_mask_image = new LLImageRaw(mWidth, mHeight, 1 ); | ||
340 | U8* baked_mask_data = baked_mask_image->getData(); | ||
341 | |||
342 | mTexLayerSet->gatherAlphaMasks(baked_mask_data, mWidth, mHeight); | ||
343 | // imdebug("lum b=8 w=%d h=%d %p", mWidth, mHeight, baked_mask_data); | ||
344 | |||
345 | |||
346 | // writes into baked_color_data | ||
347 | const char* comment_text = NULL; | ||
348 | |||
349 | S32 baked_image_components = mBumpTexName ? 5 : 4; // red green blue [bump] clothing | ||
350 | LLPointer<LLImageRaw> baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components ); | ||
351 | U8* baked_image_data = baked_image->getData(); | ||
352 | |||
353 | if( mBumpTexName ) | ||
354 | { | ||
355 | comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask | ||
356 | |||
357 | // Hide the alpha for the eyelashes in a corner of the bump map | ||
358 | if (mTexLayerSet->getBodyRegion() == "head") | ||
359 | { | ||
360 | S32 i = 0; | ||
361 | for( S32 u = 0; u < mWidth; u++ ) | ||
362 | { | ||
363 | for( S32 v = 0; v < mHeight; v++ ) | ||
364 | { | ||
365 | baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; | ||
366 | baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; | ||
367 | baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; | ||
368 | baked_image_data[5*i + 3] = baked_color_data[4*i + 3] < 255 ? baked_color_data[4*i + 3] : baked_bump_data[4*i]; | ||
369 | baked_image_data[5*i + 4] = baked_mask_data[i]; | ||
370 | i++; | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | else | ||
375 | { | ||
376 | S32 i = 0; | ||
377 | for( S32 u = 0; u < mWidth; u++ ) | ||
378 | { | ||
379 | for( S32 v = 0; v < mHeight; v++ ) | ||
380 | { | ||
381 | baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; | ||
382 | baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; | ||
383 | baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; | ||
384 | baked_image_data[5*i + 3] = baked_bump_data[4*i]; | ||
385 | baked_image_data[5*i + 4] = baked_mask_data[i]; | ||
386 | i++; | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | else | ||
392 | { | ||
393 | if (mTexLayerSet->getBodyRegion() == "skirt") | ||
394 | { | ||
395 | S32 i = 0; | ||
396 | for( S32 u = 0; u < mWidth; u++ ) | ||
397 | { | ||
398 | for( S32 v = 0; v < mHeight; v++ ) | ||
399 | { | ||
400 | baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; | ||
401 | baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; | ||
402 | baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; | ||
403 | baked_image_data[4*i + 3] = baked_color_data[4*i + 3]; // Use alpha, not bump | ||
404 | i++; | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | else | ||
409 | { | ||
410 | S32 i = 0; | ||
411 | for( S32 u = 0; u < mWidth; u++ ) | ||
412 | { | ||
413 | for( S32 v = 0; v < mHeight; v++ ) | ||
414 | { | ||
415 | baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; | ||
416 | baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; | ||
417 | baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; | ||
418 | baked_image_data[4*i + 3] = baked_mask_data[i]; | ||
419 | i++; | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | } | ||
424 | |||
425 | LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C; | ||
426 | compressedImage->setRate(0.f); | ||
427 | LLTransactionID tid; | ||
428 | LLAssetID asset_id; | ||
429 | tid.generate(); | ||
430 | asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); | ||
431 | |||
432 | BOOL res = false; | ||
433 | if( compressedImage->encode(baked_image, comment_text)) | ||
434 | { | ||
435 | res = LLVFile::writeFile(compressedImage->getData(), compressedImage->getDataSize(), | ||
436 | gVFS, asset_id, LLAssetType::AT_TEXTURE); | ||
437 | if (res) | ||
438 | { | ||
439 | LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; | ||
440 | BOOL valid = FALSE; | ||
441 | S32 file_size; | ||
442 | U8* data = LLVFile::readFile(gVFS, asset_id, LLAssetType::AT_TEXTURE, &file_size); | ||
443 | if (data) | ||
444 | { | ||
445 | valid = integrity_test->validate(data, file_size); // integrity_test will delete 'data' | ||
446 | } | ||
447 | else | ||
448 | { | ||
449 | integrity_test->setLastError("Unable to read entire file"); | ||
450 | } | ||
451 | |||
452 | if( valid ) | ||
453 | { | ||
454 | LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this ); | ||
455 | mUploadID = baked_upload_data->mID; | ||
456 | |||
457 | gAssetStorage->storeAssetData(tid, | ||
458 | LLAssetType::AT_TEXTURE, | ||
459 | LLTexLayerSetBuffer::onTextureUploadComplete, | ||
460 | baked_upload_data, | ||
461 | TRUE, // temp_file | ||
462 | FALSE, // is_priority | ||
463 | TRUE); // store_local | ||
464 | |||
465 | mNeedsUpload = FALSE; | ||
466 | } | ||
467 | else | ||
468 | { | ||
469 | mUploadPending = FALSE; | ||
470 | llinfos << "unable to create baked upload file: corrupted" << llendl; | ||
471 | LLVFile file(gVFS, asset_id, LLAssetType::AT_TEXTURE, LLVFile::WRITE); | ||
472 | file.remove(); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | if (!res) | ||
477 | { | ||
478 | mUploadPending = FALSE; | ||
479 | llinfos << "unable to create baked upload file" << llendl; | ||
480 | } | ||
481 | |||
482 | delete [] baked_color_data; | ||
483 | delete [] baked_bump_data; | ||
484 | } | ||
485 | |||
486 | |||
487 | // static | ||
488 | void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* userdata, S32 result) // StoreAssetData callback (not fixed) | ||
489 | { | ||
490 | LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)(U32)userdata; | ||
491 | |||
492 | LLVOAvatar* avatar = gAgent.getAvatarObject(); | ||
493 | |||
494 | if (0 == result && avatar && !avatar->isDead()) | ||
495 | { | ||
496 | // Sanity check: only the user's avatar should be uploading textures. | ||
497 | if( baked_upload_data->mAvatar == avatar ) | ||
498 | { | ||
499 | // Because the avatar is still valid, it's layerset buffers should be valid also. | ||
500 | LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mLayerSetBuffer; | ||
501 | layerset_buffer->mUploadPending = FALSE; | ||
502 | |||
503 | if (layerset_buffer->mUploadID.isNull()) | ||
504 | { | ||
505 | // The upload got canceled, we should be in the process of baking a new texture | ||
506 | // so request an upload with the new data | ||
507 | layerset_buffer->requestUpload(); | ||
508 | } | ||
509 | else if( baked_upload_data->mID == layerset_buffer->mUploadID ) | ||
510 | { | ||
511 | // This is the upload we're currently waiting for. | ||
512 | layerset_buffer->mUploadID.setNull(); | ||
513 | |||
514 | if( result >= 0 ) | ||
515 | { | ||
516 | LLVOAvatar::ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet ); | ||
517 | if( !gAgent.cameraCustomizeAvatar() ) | ||
518 | { | ||
519 | avatar->setNewBakedTexture( baked_te, uuid ); | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | llinfos << "LLTexLayerSetBuffer::onTextureUploadComplete() when in Customize Avatar" << llendl; | ||
524 | } | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | llinfos << "Baked upload failed. Reason: " << result << llendl; | ||
529 | // *FIX: retry upload after n seconds, asset server could be busy | ||
530 | } | ||
531 | } | ||
532 | else | ||
533 | { | ||
534 | llinfos << "Received baked texture out of date, ignored." << llendl; | ||
535 | } | ||
536 | |||
537 | avatar->dirtyMesh(); | ||
538 | } | ||
539 | } | ||
540 | else | ||
541 | { | ||
542 | // Baked texture failed to upload, but since we didn't set the new baked texture, it means that they'll | ||
543 | // try and rebake it at some point in the future (after login?) | ||
544 | llwarns << "Baked upload failed" << llendl; | ||
545 | } | ||
546 | |||
547 | delete baked_upload_data; | ||
548 | } | ||
549 | |||
550 | |||
551 | void LLTexLayerSetBuffer::bindTexture() | ||
552 | { | ||
553 | if( mInitialized ) | ||
554 | { | ||
555 | LLDynamicTexture::bindTexture(); | ||
556 | } | ||
557 | else | ||
558 | { | ||
559 | gImageList.getImage(IMG_DEFAULT)->bind(); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | void LLTexLayerSetBuffer::bindBumpTexture( U32 stage ) | ||
564 | { | ||
565 | if( mBumpTexName ) | ||
566 | { | ||
567 | LLImageGL::bindExternalTexture(mBumpTexName, stage, GL_TEXTURE_2D); | ||
568 | |||
569 | if( mLastBindTime != LLImageGL::sLastFrameTime ) | ||
570 | { | ||
571 | mLastBindTime = LLImageGL::sLastFrameTime; | ||
572 | LLImageGL::updateBoundTexMem(mWidth * mHeight * 4); | ||
573 | } | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | LLImageGL::unbindTexture(stage, GL_TEXTURE_2D); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | |||
582 | //----------------------------------------------------------------------------- | ||
583 | // LLTexLayerSet | ||
584 | // An ordered set of texture layers that get composited into a single texture. | ||
585 | //----------------------------------------------------------------------------- | ||
586 | |||
587 | LLTexLayerSetInfo::LLTexLayerSetInfo( ) | ||
588 | : | ||
589 | mBodyRegion( "" ), | ||
590 | mWidth( 512 ), | ||
591 | mHeight( 512 ), | ||
592 | mClearAlpha( TRUE ) | ||
593 | { | ||
594 | } | ||
595 | |||
596 | LLTexLayerSetInfo::~LLTexLayerSetInfo( ) | ||
597 | { | ||
598 | std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); | ||
599 | } | ||
600 | |||
601 | BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) | ||
602 | { | ||
603 | llassert( node->hasName( "layer_set" ) ); | ||
604 | if( !node->hasName( "layer_set" ) ) | ||
605 | { | ||
606 | return FALSE; | ||
607 | } | ||
608 | |||
609 | // body_region | ||
610 | static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region"); | ||
611 | if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) | ||
612 | { | ||
613 | llwarns << "<layer_set> is missing body_region attribute" << llendl; | ||
614 | return FALSE; | ||
615 | } | ||
616 | |||
617 | // width, height | ||
618 | static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); | ||
619 | if( !node->getFastAttributeS32( width_string, mWidth ) ) | ||
620 | { | ||
621 | return FALSE; | ||
622 | } | ||
623 | |||
624 | static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); | ||
625 | if( !node->getFastAttributeS32( height_string, mHeight ) ) | ||
626 | { | ||
627 | return FALSE; | ||
628 | } | ||
629 | |||
630 | // Optional alpha component to apply after all compositing is complete. | ||
631 | static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file"); | ||
632 | node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName ); | ||
633 | |||
634 | static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha"); | ||
635 | node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha ); | ||
636 | |||
637 | // <layer> | ||
638 | for (LLXmlTreeNode* child = node->getChildByName( "layer" ); | ||
639 | child; | ||
640 | child = node->getNextNamedChild()) | ||
641 | { | ||
642 | LLTexLayerInfo* info = new LLTexLayerInfo(); | ||
643 | if( !info->parseXml( child )) | ||
644 | { | ||
645 | delete info; | ||
646 | return FALSE; | ||
647 | } | ||
648 | mLayerInfoList.push_back( info ); | ||
649 | } | ||
650 | return TRUE; | ||
651 | } | ||
652 | |||
653 | //----------------------------------------------------------------------------- | ||
654 | // LLTexLayerSet | ||
655 | // An ordered set of texture layers that get composited into a single texture. | ||
656 | //----------------------------------------------------------------------------- | ||
657 | |||
658 | BOOL LLTexLayerSet::sHasCaches = FALSE; | ||
659 | |||
660 | LLTexLayerSet::LLTexLayerSet( LLVOAvatar* avatar ) | ||
661 | : | ||
662 | mComposite( NULL ), | ||
663 | mAvatar( avatar ), | ||
664 | mUpdatesEnabled( FALSE ), | ||
665 | mHasBump( FALSE ), | ||
666 | mInfo( NULL ) | ||
667 | { | ||
668 | } | ||
669 | |||
670 | LLTexLayerSet::~LLTexLayerSet() | ||
671 | { | ||
672 | std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); | ||
673 | delete mComposite; | ||
674 | } | ||
675 | |||
676 | //----------------------------------------------------------------------------- | ||
677 | // setInfo | ||
678 | //----------------------------------------------------------------------------- | ||
679 | |||
680 | BOOL LLTexLayerSet::setInfo(LLTexLayerSetInfo *info) | ||
681 | { | ||
682 | llassert(mInfo == NULL); | ||
683 | mInfo = info; | ||
684 | //mID = info->mID; // No ID | ||
685 | |||
686 | LLTexLayerSetInfo::layer_info_list_t::iterator iter; | ||
687 | mLayerList.reserve(info->mLayerInfoList.size()); | ||
688 | for (iter = info->mLayerInfoList.begin(); iter != info->mLayerInfoList.end(); iter++) | ||
689 | { | ||
690 | LLTexLayer* layer = new LLTexLayer( this ); | ||
691 | if (!layer->setInfo(*iter)) | ||
692 | { | ||
693 | mInfo = NULL; | ||
694 | return FALSE; | ||
695 | } | ||
696 | mLayerList.push_back( layer ); | ||
697 | } | ||
698 | |||
699 | requestUpdate(); | ||
700 | |||
701 | stop_glerror(); | ||
702 | |||
703 | return TRUE; | ||
704 | } | ||
705 | |||
706 | #if 0 // obsolete | ||
707 | //----------------------------------------------------------------------------- | ||
708 | // parseData | ||
709 | //----------------------------------------------------------------------------- | ||
710 | |||
711 | BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) | ||
712 | { | ||
713 | LLTexLayerSetInfo *info = new LLTexLayerSetInfo; | ||
714 | |||
715 | if (!info->parseXml(node)) | ||
716 | { | ||
717 | delete info; | ||
718 | return FALSE; | ||
719 | } | ||
720 | if (!setInfo(info)) | ||
721 | { | ||
722 | delete info; | ||
723 | return FALSE; | ||
724 | } | ||
725 | return TRUE; | ||
726 | } | ||
727 | #endif | ||
728 | |||
729 | void LLTexLayerSet::deleteCaches() | ||
730 | { | ||
731 | for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) | ||
732 | { | ||
733 | LLTexLayer* layer = *iter; | ||
734 | layer->deleteCaches(); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | // Returns TRUE if at least one packet of data has been received for each of the textures that this layerset depends on. | ||
739 | BOOL LLTexLayerSet::isLocalTextureDataAvailable() | ||
740 | { | ||
741 | return mAvatar->isLocalTextureDataAvailable( this ); | ||
742 | } | ||
743 | |||
744 | |||
745 | // Returns TRUE if all of the data for the textures that this layerset depends on have arrived. | ||
746 | BOOL LLTexLayerSet::isLocalTextureDataFinal() | ||
747 | { | ||
748 | return mAvatar->isLocalTextureDataFinal( this ); | ||
749 | } | ||
750 | |||
751 | |||
752 | BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) | ||
753 | { | ||
754 | BOOL success = TRUE; | ||
755 | |||
756 | LLGLSUIDefault gls_ui; | ||
757 | LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); | ||
758 | |||
759 | // composite color layers | ||
760 | for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) | ||
761 | { | ||
762 | LLTexLayer* layer = *iter; | ||
763 | if( layer->getRenderPass() == RP_COLOR ) | ||
764 | { | ||
765 | success &= layer->render( x, y, width, height ); | ||
766 | } | ||
767 | } | ||
768 | |||
769 | // (Optionally) replace alpha with a single component image from a tga file. | ||
770 | if( !getInfo()->mStaticAlphaFileName.empty() ) | ||
771 | { | ||
772 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
773 | glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE ); | ||
774 | glBlendFunc( GL_ONE, GL_ZERO ); | ||
775 | |||
776 | if( gUseAvatarGLCache ) | ||
777 | { | ||
778 | LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE ); | ||
779 | if( image_gl ) | ||
780 | { | ||
781 | LLGLSUIDefault gls_ui; | ||
782 | image_gl->bind(); | ||
783 | gl_rect_2d_simple_tex( width, height ); | ||
784 | } | ||
785 | else | ||
786 | { | ||
787 | success = FALSE; | ||
788 | } | ||
789 | } | ||
790 | else | ||
791 | { | ||
792 | LLImageRaw* image_raw = gTexStaticImageList.getImageRaw( getInfo()->mStaticAlphaFileName ); | ||
793 | if( image_raw ) | ||
794 | { | ||
795 | GLenum format = GL_ALPHA; | ||
796 | if( mAvatar->bindScratchTexture(format) ) | ||
797 | { | ||
798 | glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, image_raw->getWidth(), image_raw->getHeight(), format, GL_UNSIGNED_BYTE, image_raw->getData() ); | ||
799 | stop_glerror(); | ||
800 | |||
801 | gl_rect_2d_simple_tex( width, height ); | ||
802 | } | ||
803 | else | ||
804 | { | ||
805 | success = FALSE; | ||
806 | } | ||
807 | } | ||
808 | else | ||
809 | { | ||
810 | success = FALSE; | ||
811 | } | ||
812 | } | ||
813 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
814 | |||
815 | glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); | ||
816 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); | ||
817 | } | ||
818 | else | ||
819 | if( getInfo()->mClearAlpha ) | ||
820 | { | ||
821 | // Set the alpha channel to one (clean up after previous blending) | ||
822 | LLGLSNoTextureNoAlphaTest gls_no_alpha; | ||
823 | glColor4f( 0.f, 0.f, 0.f, 1.f ); | ||
824 | glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE ); | ||
825 | |||
826 | gl_rect_2d_simple( width, height ); | ||
827 | |||
828 | glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); | ||
829 | } | ||
830 | stop_glerror(); | ||
831 | |||
832 | return success; | ||
833 | } | ||
834 | |||
835 | BOOL LLTexLayerSet::renderBump( S32 x, S32 y, S32 width, S32 height ) | ||
836 | { | ||
837 | BOOL success = TRUE; | ||
838 | |||
839 | LLGLSUIDefault gls_ui; | ||
840 | LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); | ||
841 | |||
842 | //static S32 bump_layer_count = 1; | ||
843 | |||
844 | for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) | ||
845 | { | ||
846 | LLTexLayer* layer = *iter; | ||
847 | if( layer->getRenderPass() == RP_BUMP ) | ||
848 | { | ||
849 | success &= layer->render( x, y, width, height ); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | // Set the alpha channel to one (clean up after previous blending) | ||
854 | LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha; | ||
855 | glColor4f( 0.f, 0.f, 0.f, 1.f ); | ||
856 | glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE ); | ||
857 | |||
858 | gl_rect_2d_simple( width, height ); | ||
859 | |||
860 | glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); | ||
861 | stop_glerror(); | ||
862 | |||
863 | return success; | ||
864 | } | ||
865 | |||
866 | void LLTexLayerSet::requestUpdate() | ||
867 | { | ||
868 | if( mUpdatesEnabled ) | ||
869 | { | ||
870 | createComposite(); | ||
871 | mComposite->requestUpdate(); | ||
872 | } | ||
873 | } | ||
874 | |||
875 | void LLTexLayerSet::requestUpload() | ||
876 | { | ||
877 | createComposite(); | ||
878 | mComposite->requestUpload(); | ||
879 | } | ||
880 | |||
881 | void LLTexLayerSet::cancelUpload() | ||
882 | { | ||
883 | if(mComposite) | ||
884 | { | ||
885 | mComposite->cancelUpload(); | ||
886 | } | ||
887 | } | ||
888 | |||
889 | void LLTexLayerSet::createComposite() | ||
890 | { | ||
891 | if( !mComposite ) | ||
892 | { | ||
893 | S32 width = mInfo->mWidth; | ||
894 | S32 height = mInfo->mHeight; | ||
895 | // Composite other avatars at reduced resolution | ||
896 | if( !mAvatar->mIsSelf ) | ||
897 | { | ||
898 | width /= 2; | ||
899 | height /= 2; | ||
900 | } | ||
901 | mComposite = new LLTexLayerSetBuffer( this, width, height, mHasBump ); | ||
902 | } | ||
903 | } | ||
904 | |||
905 | void LLTexLayerSet::destroyComposite() | ||
906 | { | ||
907 | if( mComposite ) | ||
908 | { | ||
909 | delete mComposite; | ||
910 | mComposite = NULL; | ||
911 | } | ||
912 | } | ||
913 | |||
914 | void LLTexLayerSet::setUpdatesEnabled( BOOL b ) | ||
915 | { | ||
916 | mUpdatesEnabled = b; | ||
917 | } | ||
918 | |||
919 | |||
920 | void LLTexLayerSet::updateComposite() | ||
921 | { | ||
922 | createComposite(); | ||
923 | mComposite->updateImmediate(); | ||
924 | } | ||
925 | |||
926 | LLTexLayerSetBuffer* LLTexLayerSet::getComposite() | ||
927 | { | ||
928 | createComposite(); | ||
929 | return mComposite; | ||
930 | } | ||
931 | |||
932 | void LLTexLayerSet::gatherAlphaMasks(U8 *data, S32 width, S32 height) | ||
933 | { | ||
934 | S32 size = width * height; | ||
935 | |||
936 | memset(data, 255, width * height); | ||
937 | |||
938 | for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) | ||
939 | { | ||
940 | LLTexLayer* layer = *iter; | ||
941 | U8* alphaData = layer->getAlphaData(); | ||
942 | if (!alphaData && layer->hasAlphaParams()) | ||
943 | { | ||
944 | LLColor4 net_color; | ||
945 | layer->findNetColor( &net_color ); | ||
946 | layer->invalidateMorphMasks(); | ||
947 | layer->renderAlphaMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, &net_color); | ||
948 | alphaData = layer->getAlphaData(); | ||
949 | } | ||
950 | if (alphaData) | ||
951 | { | ||
952 | for( S32 i = 0; i < size; i++ ) | ||
953 | { | ||
954 | U8 curAlpha = data[i]; | ||
955 | U16 resultAlpha = curAlpha; | ||
956 | resultAlpha *= (alphaData[i] + 1); | ||
957 | resultAlpha = resultAlpha >> 8; | ||
958 | data[i] = (U8)resultAlpha; | ||
959 | } | ||
960 | } | ||
961 | } | ||
962 | } | ||
963 | |||
964 | void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) | ||
965 | { | ||
966 | for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ ) | ||
967 | { | ||
968 | LLTexLayer* layer = *iter; | ||
969 | layer->applyMorphMask(tex_data, width, height, num_components); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | //----------------------------------------------------------------------------- | ||
974 | // LLTexLayerInfo | ||
975 | //----------------------------------------------------------------------------- | ||
976 | LLTexLayerInfo::LLTexLayerInfo( ) | ||
977 | : | ||
978 | mWriteAllChannels( FALSE ), | ||
979 | mRenderPass( RP_COLOR ), | ||
980 | mFixedColor( 0.f, 0.f, 0.f, 0.f ), | ||
981 | mLocalTexture( -1 ), | ||
982 | mStaticImageIsMask( FALSE ), | ||
983 | mUseLocalTextureAlphaOnly( FALSE ) | ||
984 | { | ||
985 | } | ||
986 | |||
987 | LLTexLayerInfo::~LLTexLayerInfo( ) | ||
988 | { | ||
989 | std::for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer()); | ||
990 | std::for_each(mAlphaInfoList.begin(), mAlphaInfoList.end(), DeletePointer()); | ||
991 | } | ||
992 | |||
993 | BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) | ||
994 | { | ||
995 | llassert( node->hasName( "layer" ) ); | ||
996 | |||
997 | // name attribute | ||
998 | static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); | ||
999 | if( !node->getFastAttributeString( name_string, mName ) ) | ||
1000 | { | ||
1001 | return FALSE; | ||
1002 | } | ||
1003 | |||
1004 | static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); | ||
1005 | node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels ); | ||
1006 | |||
1007 | LLString render_pass_name; | ||
1008 | static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass"); | ||
1009 | if( node->getFastAttributeString( render_pass_string, render_pass_name ) ) | ||
1010 | { | ||
1011 | if( render_pass_name == "bump" ) | ||
1012 | { | ||
1013 | mRenderPass = RP_BUMP; | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a <param_color> child. | ||
1018 | // global color attribute (optional) | ||
1019 | static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); | ||
1020 | node->getFastAttributeString( global_color_string, mGlobalColor ); | ||
1021 | |||
1022 | // color attribute (optional) | ||
1023 | LLColor4U color4u; | ||
1024 | static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); | ||
1025 | if( node->getFastAttributeColor4U( fixed_color_string, color4u ) ) | ||
1026 | { | ||
1027 | mFixedColor.setVec( color4u ); | ||
1028 | } | ||
1029 | |||
1030 | // <texture> optional sub-element | ||
1031 | for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" ); | ||
1032 | texture_node; | ||
1033 | texture_node = node->getNextNamedChild()) | ||
1034 | { | ||
1035 | LLString local_texture; | ||
1036 | static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); | ||
1037 | static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); | ||
1038 | static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); | ||
1039 | static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only"); | ||
1040 | if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) | ||
1041 | { | ||
1042 | texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); | ||
1043 | } | ||
1044 | else if( texture_node->getFastAttributeString( local_texture_string, local_texture ) ) | ||
1045 | { | ||
1046 | texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); | ||
1047 | |||
1048 | if( "upper_shirt" == local_texture ) | ||
1049 | { | ||
1050 | mLocalTexture = LLVOAvatar::LOCTEX_UPPER_SHIRT; | ||
1051 | } | ||
1052 | else if( "upper_bodypaint" == local_texture ) | ||
1053 | { | ||
1054 | mLocalTexture = LLVOAvatar::LOCTEX_UPPER_BODYPAINT; | ||
1055 | } | ||
1056 | else if( "lower_pants" == local_texture ) | ||
1057 | { | ||
1058 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_PANTS; | ||
1059 | } | ||
1060 | else if( "lower_bodypaint" == local_texture ) | ||
1061 | { | ||
1062 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_BODYPAINT; | ||
1063 | } | ||
1064 | else if( "lower_shoes" == local_texture ) | ||
1065 | { | ||
1066 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SHOES; | ||
1067 | } | ||
1068 | else if( "head_bodypaint" == local_texture ) | ||
1069 | { | ||
1070 | mLocalTexture = LLVOAvatar::LOCTEX_HEAD_BODYPAINT; | ||
1071 | } | ||
1072 | else if( "lower_socks" == local_texture ) | ||
1073 | { | ||
1074 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SOCKS; | ||
1075 | } | ||
1076 | else if( "upper_jacket" == local_texture ) | ||
1077 | { | ||
1078 | mLocalTexture = LLVOAvatar::LOCTEX_UPPER_JACKET; | ||
1079 | } | ||
1080 | else if( "lower_jacket" == local_texture ) | ||
1081 | { | ||
1082 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_JACKET; | ||
1083 | } | ||
1084 | else if( "upper_gloves" == local_texture ) | ||
1085 | { | ||
1086 | mLocalTexture = LLVOAvatar::LOCTEX_UPPER_GLOVES; | ||
1087 | } | ||
1088 | else if( "upper_undershirt" == local_texture ) | ||
1089 | { | ||
1090 | mLocalTexture = LLVOAvatar::LOCTEX_UPPER_UNDERSHIRT; | ||
1091 | } | ||
1092 | else if( "lower_underpants" == local_texture ) | ||
1093 | { | ||
1094 | mLocalTexture = LLVOAvatar::LOCTEX_LOWER_UNDERPANTS; | ||
1095 | } | ||
1096 | else if( "eyes_iris" == local_texture ) | ||
1097 | { | ||
1098 | mLocalTexture = LLVOAvatar::LOCTEX_EYES_IRIS; | ||
1099 | } | ||
1100 | else if( "skirt" == local_texture ) | ||
1101 | { | ||
1102 | mLocalTexture = LLVOAvatar::LOCTEX_SKIRT; | ||
1103 | } | ||
1104 | else | ||
1105 | { | ||
1106 | llwarns << "<texture> element has invalid local_texure attribute: " << mName << " " << local_texture << llendl; | ||
1107 | return FALSE; | ||
1108 | } | ||
1109 | } | ||
1110 | else | ||
1111 | { | ||
1112 | llwarns << "<texture> element is missing a required attribute. " << mName << llendl; | ||
1113 | return FALSE; | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" ); | ||
1118 | maskNode; | ||
1119 | maskNode = node->getNextNamedChild()) | ||
1120 | { | ||
1121 | LLString morph_name; | ||
1122 | static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); | ||
1123 | if (maskNode->getFastAttributeString(morph_name_string, morph_name)) | ||
1124 | { | ||
1125 | BOOL invert = FALSE; | ||
1126 | static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); | ||
1127 | maskNode->getFastAttributeBOOL(invert_string, invert); | ||
1128 | mMorphNameList.push_back(std::pair<LLString,BOOL>(morph_name,invert)); | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | // <param> optional sub-element (color or alpha params) | ||
1133 | for (LLXmlTreeNode* child = node->getChildByName( "param" ); | ||
1134 | child; | ||
1135 | child = node->getNextNamedChild()) | ||
1136 | { | ||
1137 | if( child->getChildByName( "param_color" ) ) | ||
1138 | { | ||
1139 | // <param><param_color/></param> | ||
1140 | LLTexParamColorInfo* info = new LLTexParamColorInfo( ); | ||
1141 | if (!info->parseXml(child)) | ||
1142 | { | ||
1143 | delete info; | ||
1144 | return FALSE; | ||
1145 | } | ||
1146 | mColorInfoList.push_back( info ); | ||
1147 | } | ||
1148 | else if( child->getChildByName( "param_alpha" ) ) | ||
1149 | { | ||
1150 | // <param><param_alpha/></param> | ||
1151 | LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( ); | ||
1152 | if (!info->parseXml(child)) | ||
1153 | { | ||
1154 | delete info; | ||
1155 | return FALSE; | ||
1156 | } | ||
1157 | mAlphaInfoList.push_back( info ); | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | return TRUE; | ||
1162 | } | ||
1163 | |||
1164 | //----------------------------------------------------------------------------- | ||
1165 | // LLTexLayer | ||
1166 | // A single texture layer, consisting of: | ||
1167 | // * color, consisting of either | ||
1168 | // * one or more color parameters (weighted colors) | ||
1169 | // * a reference to a global color | ||
1170 | // * a fixed color with non-zero alpha | ||
1171 | // * opaque white (the default) | ||
1172 | // * (optional) a texture defined by either | ||
1173 | // * a GUID | ||
1174 | // * a texture entry index (TE) | ||
1175 | // * (optional) one or more alpha parameters (weighted alpha textures) | ||
1176 | //----------------------------------------------------------------------------- | ||
1177 | LLTexLayer::LLTexLayer( LLTexLayerSet* layer_set ) | ||
1178 | : | ||
1179 | mTexLayerSet( layer_set ), | ||
1180 | mMorphMasksValid( FALSE ), | ||
1181 | mStaticImageInvalid( FALSE ), | ||
1182 | mInfo( NULL ) | ||
1183 | { | ||
1184 | } | ||
1185 | |||
1186 | LLTexLayer::~LLTexLayer() | ||
1187 | { | ||
1188 | // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get | ||
1189 | // deleted with ~LLCharacter() | ||
1190 | //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer()); | ||
1191 | //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); | ||
1192 | |||
1193 | for( alpha_cache_t::iterator iter = mAlphaCache.begin(); | ||
1194 | iter != mAlphaCache.end(); iter++ ) | ||
1195 | { | ||
1196 | U8* alpha_data = iter->second; | ||
1197 | delete [] alpha_data; | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | //----------------------------------------------------------------------------- | ||
1202 | // setInfo | ||
1203 | //----------------------------------------------------------------------------- | ||
1204 | |||
1205 | BOOL LLTexLayer::setInfo(LLTexLayerInfo* info) | ||
1206 | { | ||
1207 | llassert(mInfo == NULL); | ||
1208 | mInfo = info; | ||
1209 | //mID = info->mID; // No ID | ||
1210 | |||
1211 | if (info->mRenderPass == RP_BUMP) | ||
1212 | mTexLayerSet->setBump(TRUE); | ||
1213 | |||
1214 | { | ||
1215 | LLTexLayerInfo::morph_name_list_t::iterator iter; | ||
1216 | for (iter = mInfo->mMorphNameList.begin(); iter != mInfo->mMorphNameList.end(); iter++) | ||
1217 | { | ||
1218 | // *FIX: we assume that the referenced visual param is a | ||
1219 | // morph target, need a better way of actually looking | ||
1220 | // this up. | ||
1221 | LLPolyMorphTarget *morph_param; | ||
1222 | LLString *name = &(iter->first); | ||
1223 | morph_param = (LLPolyMorphTarget *)(getTexLayerSet()->getAvatar()->getVisualParam(name->c_str())); | ||
1224 | if (morph_param) | ||
1225 | { | ||
1226 | BOOL invert = iter->second; | ||
1227 | addMaskedMorph(morph_param, invert); | ||
1228 | } | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | { | ||
1233 | LLTexLayerInfo::color_info_list_t::iterator iter; | ||
1234 | mParamColorList.reserve(mInfo->mColorInfoList.size()); | ||
1235 | for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++) | ||
1236 | { | ||
1237 | LLTexParamColor* param_color = new LLTexParamColor( this ); | ||
1238 | if (!param_color->setInfo(*iter)) | ||
1239 | { | ||
1240 | mInfo = NULL; | ||
1241 | return FALSE; | ||
1242 | } | ||
1243 | mParamColorList.push_back( param_color ); | ||
1244 | } | ||
1245 | } | ||
1246 | { | ||
1247 | LLTexLayerInfo::alpha_info_list_t::iterator iter; | ||
1248 | mParamAlphaList.reserve(mInfo->mAlphaInfoList.size()); | ||
1249 | for (iter = mInfo->mAlphaInfoList.begin(); iter != mInfo->mAlphaInfoList.end(); iter++) | ||
1250 | { | ||
1251 | LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha( this ); | ||
1252 | if (!param_alpha->setInfo(*iter)) | ||
1253 | { | ||
1254 | mInfo = NULL; | ||
1255 | return FALSE; | ||
1256 | } | ||
1257 | mParamAlphaList.push_back( param_alpha ); | ||
1258 | } | ||
1259 | } | ||
1260 | |||
1261 | return TRUE; | ||
1262 | } | ||
1263 | |||
1264 | #if 0 // obsolete | ||
1265 | //----------------------------------------------------------------------------- | ||
1266 | // parseData | ||
1267 | //----------------------------------------------------------------------------- | ||
1268 | BOOL LLTexLayer::parseData( LLXmlTreeNode* node ) | ||
1269 | { | ||
1270 | LLTexLayerInfo *info = new LLTexLayerInfo; | ||
1271 | |||
1272 | if (!info->parseXml(node)) | ||
1273 | { | ||
1274 | delete info; | ||
1275 | return FALSE; | ||
1276 | } | ||
1277 | if (!setInfo(info)) | ||
1278 | { | ||
1279 | delete info; | ||
1280 | return FALSE; | ||
1281 | } | ||
1282 | return TRUE; | ||
1283 | } | ||
1284 | #endif | ||
1285 | |||
1286 | //----------------------------------------------------------------------------- | ||
1287 | |||
1288 | |||
1289 | BOOL LLTexLayer::loadStaticImageRaw() | ||
1290 | { | ||
1291 | if( mStaticImageRaw.isNull() && !mStaticImageInvalid) | ||
1292 | { | ||
1293 | mStaticImageRaw = gTexStaticImageList.getImageRaw( getInfo()->mStaticImageFileName ); | ||
1294 | // We now have something in one of our caches | ||
1295 | LLTexLayerSet::sHasCaches |= mStaticImageRaw.notNull() ? TRUE : FALSE; | ||
1296 | if( mStaticImageRaw.isNull() ) | ||
1297 | { | ||
1298 | llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl; | ||
1299 | mStaticImageInvalid = TRUE; // don't try again. | ||
1300 | return FALSE; | ||
1301 | } | ||
1302 | } | ||
1303 | return TRUE; | ||
1304 | } | ||
1305 | |||
1306 | void LLTexLayer::deleteCaches() | ||
1307 | { | ||
1308 | for( alpha_list_t::iterator iter = mParamAlphaList.begin(); | ||
1309 | iter != mParamAlphaList.end(); iter++ ) | ||
1310 | { | ||
1311 | LLTexLayerParamAlpha* param = *iter; | ||
1312 | param->deleteCaches(); | ||
1313 | } | ||
1314 | mStaticImageRaw = NULL; | ||
1315 | } | ||
1316 | |||
1317 | BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) | ||
1318 | { | ||
1319 | LLGLEnable color_mat(GL_COLOR_MATERIAL); | ||
1320 | gPipeline.disableLights(); | ||
1321 | |||
1322 | BOOL success = TRUE; | ||
1323 | |||
1324 | BOOL color_specified = FALSE; | ||
1325 | BOOL alpha_mask_specified = FALSE; | ||
1326 | |||
1327 | LLColor4 net_color; | ||
1328 | color_specified = findNetColor( &net_color ); | ||
1329 | |||
1330 | // If you can't see the layer, don't render it. | ||
1331 | if( is_approx_zero( net_color.mV[VW] ) ) | ||
1332 | { | ||
1333 | return success; | ||
1334 | } | ||
1335 | |||
1336 | alpha_list_t::iterator iter = mParamAlphaList.begin(); | ||
1337 | if( iter != mParamAlphaList.end() ) | ||
1338 | { | ||
1339 | // If we have alpha masks, but we're skipping all of them, skip the whole layer. | ||
1340 | // However, we can't do this optimization if we have morph masks that need updating. | ||
1341 | if( mMaskedMorphs.empty() ) | ||
1342 | { | ||
1343 | BOOL skip_layer = TRUE; | ||
1344 | |||
1345 | while( iter != mParamAlphaList.end() ) | ||
1346 | { | ||
1347 | LLTexLayerParamAlpha* param = *iter; | ||
1348 | |||
1349 | if( !param->getSkip() ) | ||
1350 | { | ||
1351 | skip_layer = FALSE; | ||
1352 | break; | ||
1353 | } | ||
1354 | |||
1355 | iter++; | ||
1356 | } | ||
1357 | |||
1358 | if( skip_layer ) | ||
1359 | { | ||
1360 | return success; | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | renderAlphaMasks( x, y, width, height, &net_color ); | ||
1365 | alpha_mask_specified = TRUE; | ||
1366 | glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA ); | ||
1367 | } | ||
1368 | |||
1369 | glColor4fv( net_color.mV); | ||
1370 | |||
1371 | if( getInfo()->mWriteAllChannels ) | ||
1372 | { | ||
1373 | glBlendFunc( GL_ONE, GL_ZERO ); | ||
1374 | } | ||
1375 | |||
1376 | if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) | ||
1377 | { | ||
1378 | if( gUseAvatarGLCache ) | ||
1379 | { | ||
1380 | LLImageGL* image_gl = NULL; | ||
1381 | if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) | ||
1382 | { | ||
1383 | if( image_gl ) | ||
1384 | { | ||
1385 | LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0); | ||
1386 | |||
1387 | BOOL old_clamps = image_gl->getClampS(); | ||
1388 | BOOL old_clampt = image_gl->getClampT(); | ||
1389 | |||
1390 | image_gl->bind(); | ||
1391 | image_gl->setClamp(TRUE, TRUE); | ||
1392 | |||
1393 | gl_rect_2d_simple_tex( width, height ); | ||
1394 | |||
1395 | image_gl->setClamp(old_clamps, old_clampt); | ||
1396 | image_gl->unbindTexture(0, GL_TEXTURE_2D); | ||
1397 | } | ||
1398 | } | ||
1399 | else | ||
1400 | { | ||
1401 | success = FALSE; | ||
1402 | } | ||
1403 | } | ||
1404 | else | ||
1405 | { | ||
1406 | LLPointer<LLImageRaw> image_raw = new LLImageRaw; | ||
1407 | if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) ) | ||
1408 | { | ||
1409 | success &= renderImageRaw( image_raw->getData(), | ||
1410 | image_raw->getWidth(), | ||
1411 | image_raw->getHeight(), | ||
1412 | image_raw->getComponents(), | ||
1413 | width, | ||
1414 | height, | ||
1415 | FALSE ); | ||
1416 | } | ||
1417 | else | ||
1418 | { | ||
1419 | success = FALSE; | ||
1420 | } | ||
1421 | } | ||
1422 | } | ||
1423 | |||
1424 | if( !getInfo()->mStaticImageFileName.empty() ) | ||
1425 | { | ||
1426 | if( gUseAvatarGLCache ) | ||
1427 | { | ||
1428 | LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); | ||
1429 | if( image_gl ) | ||
1430 | { | ||
1431 | image_gl->bind(); | ||
1432 | gl_rect_2d_simple_tex( width, height ); | ||
1433 | image_gl->unbindTexture(0, GL_TEXTURE_2D); | ||
1434 | } | ||
1435 | else | ||
1436 | { | ||
1437 | success = FALSE; | ||
1438 | } | ||
1439 | } | ||
1440 | else | ||
1441 | { | ||
1442 | // Don't load the image file until we actually need it the first time. Like now. | ||
1443 | if (!loadStaticImageRaw()) | ||
1444 | { | ||
1445 | success = FALSE; | ||
1446 | } | ||
1447 | if( mStaticImageRaw.notNull() ) | ||
1448 | { | ||
1449 | success &= renderImageRaw( | ||
1450 | mStaticImageRaw->getData(), | ||
1451 | mStaticImageRaw->getWidth(), | ||
1452 | mStaticImageRaw->getHeight(), | ||
1453 | mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask ); | ||
1454 | } | ||
1455 | else | ||
1456 | { | ||
1457 | success = FALSE; | ||
1458 | } | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 | if( ((-1 == getInfo()->mLocalTexture) || | ||
1463 | getInfo()->mUseLocalTextureAlphaOnly) && | ||
1464 | getInfo()->mStaticImageFileName.empty() && | ||
1465 | color_specified ) | ||
1466 | { | ||
1467 | LLGLSNoTextureNoAlphaTest gls; | ||
1468 | glColor4fv( net_color.mV); | ||
1469 | gl_rect_2d_simple( width, height ); | ||
1470 | } | ||
1471 | |||
1472 | if( alpha_mask_specified || getInfo()->mWriteAllChannels ) | ||
1473 | { | ||
1474 | // Restore standard blend func value | ||
1475 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); | ||
1476 | stop_glerror(); | ||
1477 | } | ||
1478 | |||
1479 | if( !success ) | ||
1480 | { | ||
1481 | llinfos << "LLTexLayer::render() partial: " << getInfo()->mName << llendl; | ||
1482 | } | ||
1483 | return success; | ||
1484 | } | ||
1485 | |||
1486 | U8* LLTexLayer::getAlphaData() | ||
1487 | { | ||
1488 | LLCRC alpha_mask_crc; | ||
1489 | const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture); | ||
1490 | alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); | ||
1491 | |||
1492 | for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) | ||
1493 | { | ||
1494 | LLTexLayerParamAlpha* param = *iter; | ||
1495 | F32 param_weight = param->getWeight(); | ||
1496 | alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); | ||
1497 | } | ||
1498 | |||
1499 | U32 cache_index = alpha_mask_crc.getCRC(); | ||
1500 | |||
1501 | alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index); | ||
1502 | return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; | ||
1503 | } | ||
1504 | |||
1505 | BOOL LLTexLayer::findNetColor( LLColor4* net_color ) | ||
1506 | { | ||
1507 | // Color is either: | ||
1508 | // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) | ||
1509 | // * a reference to a global color | ||
1510 | // * a fixed color with non-zero alpha | ||
1511 | // * opaque white (the default) | ||
1512 | |||
1513 | if( !mParamColorList.empty() ) | ||
1514 | { | ||
1515 | if( !getGlobalColor().empty() ) | ||
1516 | { | ||
1517 | net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getInfo()->mGlobalColor ) ); | ||
1518 | } | ||
1519 | else | ||
1520 | if( getInfo()->mFixedColor.mV[VW] ) | ||
1521 | { | ||
1522 | net_color->setVec( getInfo()->mFixedColor ); | ||
1523 | } | ||
1524 | else | ||
1525 | { | ||
1526 | net_color->setVec( 0.f, 0.f, 0.f, 0.f ); | ||
1527 | } | ||
1528 | |||
1529 | for( color_list_t::iterator iter = mParamColorList.begin(); | ||
1530 | iter != mParamColorList.end(); iter++ ) | ||
1531 | { | ||
1532 | LLTexParamColor* param = *iter; | ||
1533 | LLColor4 param_net = param->getNetColor(); | ||
1534 | switch( param->getOperation() ) | ||
1535 | { | ||
1536 | case OP_ADD: | ||
1537 | *net_color += param_net; | ||
1538 | break; | ||
1539 | case OP_MULTIPLY: | ||
1540 | net_color->mV[VX] *= param_net.mV[VX]; | ||
1541 | net_color->mV[VY] *= param_net.mV[VY]; | ||
1542 | net_color->mV[VZ] *= param_net.mV[VZ]; | ||
1543 | net_color->mV[VW] *= param_net.mV[VW]; | ||
1544 | break; | ||
1545 | case OP_BLEND: | ||
1546 | net_color->setVec( lerp(*net_color, param_net, param->getWeight()) ); | ||
1547 | break; | ||
1548 | default: | ||
1549 | llassert(0); | ||
1550 | break; | ||
1551 | } | ||
1552 | } | ||
1553 | return TRUE; | ||
1554 | } | ||
1555 | |||
1556 | if( !getGlobalColor().empty() ) | ||
1557 | { | ||
1558 | net_color->setVec( mTexLayerSet->getAvatar()->getGlobalColor( getGlobalColor() ) ); | ||
1559 | return TRUE; | ||
1560 | } | ||
1561 | |||
1562 | if( getInfo()->mFixedColor.mV[VW] ) | ||
1563 | { | ||
1564 | net_color->setVec( getInfo()->mFixedColor ); | ||
1565 | return TRUE; | ||
1566 | } | ||
1567 | |||
1568 | net_color->setToWhite(); | ||
1569 | |||
1570 | return FALSE; // No need to draw a separate colored polygon | ||
1571 | } | ||
1572 | |||
1573 | |||
1574 | BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4* colorp ) | ||
1575 | { | ||
1576 | BOOL success = TRUE; | ||
1577 | |||
1578 | llassert( !mParamAlphaList.empty() ); | ||
1579 | |||
1580 | glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE ); | ||
1581 | |||
1582 | alpha_list_t::iterator iter = mParamAlphaList.begin(); | ||
1583 | LLTexLayerParamAlpha* first_param = *iter; | ||
1584 | |||
1585 | // Note: if the first param is a mulitply, multiply against the current buffer's alpha | ||
1586 | if( !first_param || !first_param->getMultiplyBlend() ) | ||
1587 | { | ||
1588 | LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test; | ||
1589 | |||
1590 | // Clear the alpha | ||
1591 | glBlendFunc( GL_ONE, GL_ZERO ); | ||
1592 | |||
1593 | glColor4f( 0.f, 0.f, 0.f, 0.f ); | ||
1594 | gl_rect_2d_simple( width, height ); | ||
1595 | } | ||
1596 | |||
1597 | // Accumulate alphas | ||
1598 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
1599 | glColor4f( 1.f, 1.f, 1.f, 1.f ); | ||
1600 | |||
1601 | for( iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) | ||
1602 | { | ||
1603 | LLTexLayerParamAlpha* param = *iter; | ||
1604 | success &= param->render( x, y, width, height ); | ||
1605 | } | ||
1606 | |||
1607 | // Approximates a min() function | ||
1608 | glBlendFunc( GL_DST_ALPHA, GL_ZERO ); | ||
1609 | |||
1610 | // Accumulate the alpha component of the texture | ||
1611 | if( getInfo()->mLocalTexture != -1 ) | ||
1612 | { | ||
1613 | if( gUseAvatarGLCache ) | ||
1614 | { | ||
1615 | LLImageGL* image_gl = NULL; | ||
1616 | if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) | ||
1617 | { | ||
1618 | if( image_gl && (image_gl->getComponents() == 4) ) | ||
1619 | { | ||
1620 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
1621 | |||
1622 | BOOL old_clamps = image_gl->getClampS(); | ||
1623 | BOOL old_clampt = image_gl->getClampT(); | ||
1624 | image_gl->bind(); | ||
1625 | image_gl->setClamp(TRUE, TRUE); | ||
1626 | |||
1627 | gl_rect_2d_simple_tex( width, height ); | ||
1628 | |||
1629 | image_gl->setClamp(old_clamps, old_clampt); | ||
1630 | image_gl->unbindTexture(0, GL_TEXTURE_2D); | ||
1631 | } | ||
1632 | } | ||
1633 | else | ||
1634 | { | ||
1635 | success = FALSE; | ||
1636 | } | ||
1637 | } | ||
1638 | else | ||
1639 | { | ||
1640 | LLPointer<LLImageRaw> image_raw = new LLImageRaw; | ||
1641 | if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) ) | ||
1642 | { | ||
1643 | if(image_raw->getComponents() == 4) | ||
1644 | { | ||
1645 | success &= renderImageRaw( | ||
1646 | image_raw->getData(), | ||
1647 | image_raw->getWidth(), | ||
1648 | image_raw->getHeight(), | ||
1649 | image_raw->getComponents(), width, height, FALSE ); | ||
1650 | } | ||
1651 | } | ||
1652 | else | ||
1653 | { | ||
1654 | success = FALSE; | ||
1655 | } | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | if( !getInfo()->mStaticImageFileName.empty() ) | ||
1660 | { | ||
1661 | if( gUseAvatarGLCache ) | ||
1662 | { | ||
1663 | LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); | ||
1664 | if( image_gl ) | ||
1665 | { | ||
1666 | if( (image_gl->getComponents() == 4) || | ||
1667 | ( (image_gl->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) | ||
1668 | { | ||
1669 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
1670 | image_gl->bind(); | ||
1671 | gl_rect_2d_simple_tex( width, height ); | ||
1672 | image_gl->unbindTexture(0, GL_TEXTURE_2D); | ||
1673 | } | ||
1674 | } | ||
1675 | else | ||
1676 | { | ||
1677 | success = FALSE; | ||
1678 | } | ||
1679 | } | ||
1680 | else | ||
1681 | { | ||
1682 | // Don't load the image file until we actually need it the first time. Like now. | ||
1683 | if (!loadStaticImageRaw()) | ||
1684 | { | ||
1685 | success = FALSE; | ||
1686 | } | ||
1687 | |||
1688 | if( mStaticImageRaw.notNull() ) | ||
1689 | { | ||
1690 | if( (mStaticImageRaw->getComponents() == 4) || | ||
1691 | ( (mStaticImageRaw->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) | ||
1692 | { | ||
1693 | success &= renderImageRaw( | ||
1694 | mStaticImageRaw->getData(), | ||
1695 | mStaticImageRaw->getWidth(), | ||
1696 | mStaticImageRaw->getHeight(), | ||
1697 | mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask ); | ||
1698 | } | ||
1699 | } | ||
1700 | else | ||
1701 | { | ||
1702 | success = FALSE; | ||
1703 | } | ||
1704 | } | ||
1705 | } | ||
1706 | |||
1707 | // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. | ||
1708 | // Note: we're still using glBlendFunc( GL_DST_ALPHA, GL_ZERO ); | ||
1709 | if( colorp->mV[VW] != 1.f ) | ||
1710 | { | ||
1711 | LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test; | ||
1712 | glColor4fv( colorp->mV ); | ||
1713 | gl_rect_2d_simple( width, height ); | ||
1714 | } | ||
1715 | |||
1716 | |||
1717 | LLGLSUIDefault gls_ui; | ||
1718 | |||
1719 | glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); | ||
1720 | |||
1721 | if (!mMorphMasksValid && !mMaskedMorphs.empty()) | ||
1722 | { | ||
1723 | LLCRC alpha_mask_crc; | ||
1724 | const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture); | ||
1725 | alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); | ||
1726 | |||
1727 | for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) | ||
1728 | { | ||
1729 | LLTexLayerParamAlpha* param = *iter; | ||
1730 | F32 param_weight = param->getWeight(); | ||
1731 | alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); | ||
1732 | } | ||
1733 | |||
1734 | U32 cache_index = alpha_mask_crc.getCRC(); | ||
1735 | |||
1736 | alpha_cache_t::iterator iter2 = mAlphaCache.find(cache_index); | ||
1737 | U8* alpha_data; | ||
1738 | if (iter2 != mAlphaCache.end()) | ||
1739 | { | ||
1740 | alpha_data = iter2->second; | ||
1741 | } | ||
1742 | else | ||
1743 | { | ||
1744 | // clear out a slot if we have filled our cache | ||
1745 | S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1; | ||
1746 | while ((S32)mAlphaCache.size() >= max_cache_entries) | ||
1747 | { | ||
1748 | iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry | ||
1749 | alpha_data = iter2->second; | ||
1750 | delete [] alpha_data; | ||
1751 | mAlphaCache.erase(iter2); | ||
1752 | } | ||
1753 | alpha_data = new U8[width * height]; | ||
1754 | mAlphaCache[cache_index] = alpha_data; | ||
1755 | glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data); | ||
1756 | } | ||
1757 | |||
1758 | getTexLayerSet()->getAvatar()->dirtyMesh(); | ||
1759 | |||
1760 | mMorphMasksValid = TRUE; | ||
1761 | |||
1762 | for( morph_list_t::iterator iter3 = mMaskedMorphs.begin(); | ||
1763 | iter3 != mMaskedMorphs.end(); iter3++ ) | ||
1764 | { | ||
1765 | LLMaskedMorph* maskedMorph = &(*iter3); | ||
1766 | maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert); | ||
1767 | } | ||
1768 | } | ||
1769 | |||
1770 | return success; | ||
1771 | } | ||
1772 | |||
1773 | void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) | ||
1774 | { | ||
1775 | for( morph_list_t::iterator iter = mMaskedMorphs.begin(); | ||
1776 | iter != mMaskedMorphs.end(); iter++ ) | ||
1777 | { | ||
1778 | LLMaskedMorph* maskedMorph = &(*iter); | ||
1779 | maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); | ||
1780 | } | ||
1781 | } | ||
1782 | |||
1783 | // Returns TRUE on success. | ||
1784 | BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask ) | ||
1785 | { | ||
1786 | if (!in_data) | ||
1787 | { | ||
1788 | return FALSE; | ||
1789 | } | ||
1790 | GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; | ||
1791 | GLenum format = format_options[in_components-1]; | ||
1792 | if( is_mask ) | ||
1793 | { | ||
1794 | llassert( 1 == in_components ); | ||
1795 | format = GL_ALPHA; | ||
1796 | } | ||
1797 | |||
1798 | if( (in_width != VOAVATAR_SCRATCH_TEX_WIDTH) || (in_height != VOAVATAR_SCRATCH_TEX_HEIGHT) ) | ||
1799 | { | ||
1800 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
1801 | |||
1802 | GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; | ||
1803 | GLenum internal_format = internal_format_options[in_components-1]; | ||
1804 | if( is_mask ) | ||
1805 | { | ||
1806 | llassert( 1 == in_components ); | ||
1807 | internal_format = GL_ALPHA8; | ||
1808 | } | ||
1809 | |||
1810 | GLuint name = 0; | ||
1811 | glGenTextures(1, &name ); | ||
1812 | stop_glerror(); | ||
1813 | |||
1814 | LLImageGL::bindExternalTexture( name, 0, GL_TEXTURE_2D ); | ||
1815 | stop_glerror(); | ||
1816 | |||
1817 | glTexImage2D( | ||
1818 | GL_TEXTURE_2D, 0, internal_format, | ||
1819 | in_width, in_height, | ||
1820 | 0, format, GL_UNSIGNED_BYTE, in_data ); | ||
1821 | stop_glerror(); | ||
1822 | |||
1823 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
1824 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
1825 | |||
1826 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
1827 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
1828 | |||
1829 | gl_rect_2d_simple_tex( width, height ); | ||
1830 | |||
1831 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
1832 | |||
1833 | glDeleteTextures(1, &name ); | ||
1834 | stop_glerror(); | ||
1835 | } | ||
1836 | else | ||
1837 | { | ||
1838 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
1839 | |||
1840 | if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) ) | ||
1841 | { | ||
1842 | return FALSE; | ||
1843 | } | ||
1844 | |||
1845 | glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data ); | ||
1846 | stop_glerror(); | ||
1847 | |||
1848 | gl_rect_2d_simple_tex( width, height ); | ||
1849 | |||
1850 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
1851 | } | ||
1852 | |||
1853 | return TRUE; | ||
1854 | } | ||
1855 | |||
1856 | void LLTexLayer::requestUpdate() | ||
1857 | { | ||
1858 | mTexLayerSet->requestUpdate(); | ||
1859 | } | ||
1860 | |||
1861 | void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert) | ||
1862 | { | ||
1863 | mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert)); | ||
1864 | } | ||
1865 | |||
1866 | void LLTexLayer::invalidateMorphMasks() | ||
1867 | { | ||
1868 | mMorphMasksValid = FALSE; | ||
1869 | } | ||
1870 | |||
1871 | //----------------------------------------------------------------------------- | ||
1872 | // LLTexLayerParamAlphaInfo | ||
1873 | //----------------------------------------------------------------------------- | ||
1874 | LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo( ) | ||
1875 | : | ||
1876 | mMultiplyBlend( FALSE ), | ||
1877 | mSkipIfZeroWeight( FALSE ), | ||
1878 | mDomain( 0.f ) | ||
1879 | { | ||
1880 | } | ||
1881 | |||
1882 | BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) | ||
1883 | { | ||
1884 | llassert( node->hasName( "param" ) && node->getChildByName( "param_alpha" ) ); | ||
1885 | |||
1886 | if( !LLViewerVisualParamInfo::parseXml(node) ) | ||
1887 | return FALSE; | ||
1888 | |||
1889 | LLXmlTreeNode* param_alpha_node = node->getChildByName( "param_alpha" ); | ||
1890 | if( !param_alpha_node ) | ||
1891 | { | ||
1892 | return FALSE; | ||
1893 | } | ||
1894 | |||
1895 | static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); | ||
1896 | if( param_alpha_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) | ||
1897 | { | ||
1898 | // Don't load the image file until it's actually needed. | ||
1899 | } | ||
1900 | // else | ||
1901 | // { | ||
1902 | // llwarns << "<param_alpha> element is missing tga_file attribute." << llendl; | ||
1903 | // } | ||
1904 | |||
1905 | static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); | ||
1906 | param_alpha_node->getFastAttributeBOOL( multiply_blend_string, mMultiplyBlend ); | ||
1907 | |||
1908 | static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); | ||
1909 | param_alpha_node->getFastAttributeBOOL( skip_if_zero_string, mSkipIfZeroWeight ); | ||
1910 | |||
1911 | static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); | ||
1912 | param_alpha_node->getFastAttributeF32( domain_string, mDomain ); | ||
1913 | |||
1914 | gGradientPaletteList.initPalette(mDomain); | ||
1915 | |||
1916 | return TRUE; | ||
1917 | } | ||
1918 | |||
1919 | //----------------------------------------------------------------------------- | ||
1920 | // LLTexLayerParamAlpha | ||
1921 | //----------------------------------------------------------------------------- | ||
1922 | |||
1923 | // static | ||
1924 | LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; | ||
1925 | |||
1926 | // static | ||
1927 | void LLTexLayerParamAlpha::dumpCacheByteCount() | ||
1928 | { | ||
1929 | S32 gl_bytes = 0; | ||
1930 | getCacheByteCount( &gl_bytes ); | ||
1931 | llinfos << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << llendl; | ||
1932 | } | ||
1933 | |||
1934 | // static | ||
1935 | void LLTexLayerParamAlpha::getCacheByteCount( S32* gl_bytes ) | ||
1936 | { | ||
1937 | *gl_bytes = 0; | ||
1938 | |||
1939 | for( param_alpha_ptr_list_t::iterator iter = sInstances.begin(); | ||
1940 | iter != sInstances.end(); iter++ ) | ||
1941 | { | ||
1942 | LLTexLayerParamAlpha* instance = *iter; | ||
1943 | LLImageGL* image_gl = instance->mCachedProcessedImageGL; | ||
1944 | if( image_gl ) | ||
1945 | { | ||
1946 | S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); | ||
1947 | |||
1948 | if( image_gl->getHasGLTexture() ) | ||
1949 | { | ||
1950 | *gl_bytes += bytes; | ||
1951 | } | ||
1952 | } | ||
1953 | } | ||
1954 | } | ||
1955 | |||
1956 | LLTexLayerParamAlpha::LLTexLayerParamAlpha( LLTexLayer* layer ) | ||
1957 | : | ||
1958 | mCachedProcessedImageGL( NULL ), | ||
1959 | mTexLayer( layer ), | ||
1960 | mNeedsCreateTexture( FALSE ), | ||
1961 | mStaticImageInvalid( FALSE ), | ||
1962 | mAvgDistortionVec(1.f, 1.f, 1.f), | ||
1963 | mCachedEffectiveWeight(0.f) | ||
1964 | { | ||
1965 | sInstances.push_front( this ); | ||
1966 | } | ||
1967 | |||
1968 | LLTexLayerParamAlpha::~LLTexLayerParamAlpha() | ||
1969 | { | ||
1970 | deleteCaches(); | ||
1971 | sInstances.remove( this ); | ||
1972 | } | ||
1973 | |||
1974 | //----------------------------------------------------------------------------- | ||
1975 | // setInfo() | ||
1976 | //----------------------------------------------------------------------------- | ||
1977 | BOOL LLTexLayerParamAlpha::setInfo(LLTexLayerParamAlphaInfo *info) | ||
1978 | { | ||
1979 | llassert(mInfo == NULL); | ||
1980 | if (info->mID < 0) | ||
1981 | return FALSE; | ||
1982 | mInfo = info; | ||
1983 | mID = info->mID; | ||
1984 | |||
1985 | mTexLayer->getTexLayerSet()->getAvatar()->addVisualParam( this ); | ||
1986 | setWeight(getDefaultWeight(), FALSE ); | ||
1987 | |||
1988 | return TRUE; | ||
1989 | } | ||
1990 | |||
1991 | //----------------------------------------------------------------------------- | ||
1992 | |||
1993 | void LLTexLayerParamAlpha::deleteCaches() | ||
1994 | { | ||
1995 | mStaticImageTGA = NULL; // deletes image | ||
1996 | mCachedProcessedImageGL = NULL; | ||
1997 | mStaticImageRaw = NULL; | ||
1998 | mNeedsCreateTexture = FALSE; | ||
1999 | } | ||
2000 | |||
2001 | void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) | ||
2002 | { | ||
2003 | if (mIsAnimating) | ||
2004 | { | ||
2005 | return; | ||
2006 | } | ||
2007 | F32 min_weight = getMinWeight(); | ||
2008 | F32 max_weight = getMaxWeight(); | ||
2009 | F32 new_weight = llclamp(weight, min_weight, max_weight); | ||
2010 | U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight ); | ||
2011 | U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight ); | ||
2012 | if( cur_u8 != new_u8) | ||
2013 | { | ||
2014 | mCurWeight = new_weight; | ||
2015 | |||
2016 | LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar(); | ||
2017 | if( avatar->getSex() & getSex() ) | ||
2018 | { | ||
2019 | avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); | ||
2020 | mTexLayer->invalidateMorphMasks(); | ||
2021 | } | ||
2022 | } | ||
2023 | } | ||
2024 | |||
2025 | void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user) | ||
2026 | { | ||
2027 | mTargetWeight = target_value; | ||
2028 | setWeight(target_value, set_by_user); | ||
2029 | mIsAnimating = TRUE; | ||
2030 | if (mNext) | ||
2031 | { | ||
2032 | mNext->setAnimationTarget(target_value, set_by_user); | ||
2033 | } | ||
2034 | } | ||
2035 | |||
2036 | void LLTexLayerParamAlpha::animate(F32 delta, BOOL set_by_user) | ||
2037 | { | ||
2038 | if (mNext) | ||
2039 | { | ||
2040 | mNext->animate(delta, set_by_user); | ||
2041 | } | ||
2042 | } | ||
2043 | |||
2044 | BOOL LLTexLayerParamAlpha::getSkip() | ||
2045 | { | ||
2046 | LLVOAvatar *avatar = mTexLayer->getTexLayerSet()->getAvatar(); | ||
2047 | |||
2048 | if( getInfo()->mSkipIfZeroWeight ) | ||
2049 | { | ||
2050 | F32 effective_weight = ( avatar->getSex() & getSex() ) ? mCurWeight : getDefaultWeight(); | ||
2051 | if (is_approx_zero( effective_weight )) | ||
2052 | { | ||
2053 | return TRUE; | ||
2054 | } | ||
2055 | } | ||
2056 | |||
2057 | EWearableType type = (EWearableType)getWearableType(); | ||
2058 | if( (type != WT_INVALID) && !avatar->isWearingWearableType( type ) ) | ||
2059 | { | ||
2060 | return TRUE; | ||
2061 | } | ||
2062 | |||
2063 | return FALSE; | ||
2064 | } | ||
2065 | |||
2066 | |||
2067 | BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) | ||
2068 | { | ||
2069 | BOOL success = TRUE; | ||
2070 | |||
2071 | F32 effective_weight = ( mTexLayer->getTexLayerSet()->getAvatar()->getSex() & getSex() ) ? mCurWeight : getDefaultWeight(); | ||
2072 | BOOL weight_changed = effective_weight != mCachedEffectiveWeight; | ||
2073 | if( getSkip() ) | ||
2074 | { | ||
2075 | return success; | ||
2076 | } | ||
2077 | |||
2078 | if( getInfo()->mMultiplyBlend ) | ||
2079 | { | ||
2080 | glBlendFunc( GL_DST_ALPHA, GL_ZERO ); // Multiplication: approximates a min() function | ||
2081 | } | ||
2082 | else | ||
2083 | { | ||
2084 | glBlendFunc( GL_ONE, GL_ONE ); // Addition: approximates a max() function | ||
2085 | } | ||
2086 | |||
2087 | if( !getInfo()->mStaticImageFileName.empty() && !mStaticImageInvalid) | ||
2088 | { | ||
2089 | if( mStaticImageTGA.isNull() ) | ||
2090 | { | ||
2091 | // Don't load the image file until we actually need it the first time. Like now. | ||
2092 | mStaticImageTGA = gTexStaticImageList.getImageTGA( getInfo()->mStaticImageFileName ); | ||
2093 | // We now have something in one of our caches | ||
2094 | LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE; | ||
2095 | |||
2096 | if( mStaticImageTGA.isNull() ) | ||
2097 | { | ||
2098 | llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl; | ||
2099 | mStaticImageInvalid = TRUE; // don't try again. | ||
2100 | return FALSE; | ||
2101 | } | ||
2102 | } | ||
2103 | |||
2104 | const S32 image_tga_width = mStaticImageTGA->getWidth(); | ||
2105 | const S32 image_tga_height = mStaticImageTGA->getHeight(); | ||
2106 | if( !mCachedProcessedImageGL || | ||
2107 | (mCachedProcessedImageGL->getWidth() != image_tga_width) || | ||
2108 | (mCachedProcessedImageGL->getHeight() != image_tga_height) || | ||
2109 | (weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) || | ||
2110 | (!gUseAvatarGLCache) ) | ||
2111 | { | ||
2112 | // llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; | ||
2113 | mCachedEffectiveWeight = effective_weight; | ||
2114 | |||
2115 | if( !mCachedProcessedImageGL ) | ||
2116 | { | ||
2117 | mCachedProcessedImageGL = new LLImageGL( image_tga_width, image_tga_height, 1, FALSE); | ||
2118 | |||
2119 | // We now have something in one of our caches | ||
2120 | LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE; | ||
2121 | |||
2122 | if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) | ||
2123 | { | ||
2124 | // interpret luminance values as color index table | ||
2125 | mCachedProcessedImageGL->setExplicitFormat( GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX ); | ||
2126 | } | ||
2127 | else | ||
2128 | { | ||
2129 | mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); | ||
2130 | } | ||
2131 | } | ||
2132 | |||
2133 | // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. | ||
2134 | if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) | ||
2135 | { | ||
2136 | mStaticImageRaw = NULL; | ||
2137 | mStaticImageRaw = new LLImageRaw; | ||
2138 | mStaticImageTGA->decode(mStaticImageRaw); | ||
2139 | mNeedsCreateTexture = TRUE; | ||
2140 | } | ||
2141 | else | ||
2142 | { | ||
2143 | mStaticImageRaw = NULL; | ||
2144 | mStaticImageRaw = new LLImageRaw; | ||
2145 | mStaticImageTGA->decodeAndProcess( mStaticImageRaw, getInfo()->mDomain, effective_weight ); | ||
2146 | mNeedsCreateTexture = TRUE; | ||
2147 | } | ||
2148 | } | ||
2149 | |||
2150 | if( mCachedProcessedImageGL ) | ||
2151 | { | ||
2152 | if( gUseAvatarGLCache ) // 64 MB | ||
2153 | { | ||
2154 | if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) | ||
2155 | { | ||
2156 | if( mNeedsCreateTexture ) | ||
2157 | { | ||
2158 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); | ||
2159 | mNeedsCreateTexture = FALSE; | ||
2160 | |||
2161 | mCachedProcessedImageGL->bind(); | ||
2162 | mCachedProcessedImageGL->setClamp(TRUE, TRUE); | ||
2163 | } | ||
2164 | |||
2165 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2166 | mCachedProcessedImageGL->bind(); | ||
2167 | gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight ); | ||
2168 | gl_rect_2d_simple_tex( width, height ); | ||
2169 | mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D); | ||
2170 | } | ||
2171 | else | ||
2172 | { | ||
2173 | // Create the GL texture, and then hang onto it for future use. | ||
2174 | if( mNeedsCreateTexture ) | ||
2175 | { | ||
2176 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); | ||
2177 | mNeedsCreateTexture = FALSE; | ||
2178 | |||
2179 | mCachedProcessedImageGL->bind(); | ||
2180 | mCachedProcessedImageGL->setClamp(TRUE, TRUE); | ||
2181 | } | ||
2182 | |||
2183 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2184 | mCachedProcessedImageGL->bind(); | ||
2185 | gl_rect_2d_simple_tex( width, height ); | ||
2186 | mCachedProcessedImageGL->unbindTexture(0, GL_TEXTURE_2D); | ||
2187 | } | ||
2188 | stop_glerror(); | ||
2189 | } | ||
2190 | else | ||
2191 | { | ||
2192 | if( (mCachedProcessedImageGL->getWidth() != VOAVATAR_SCRATCH_TEX_WIDTH) || | ||
2193 | (mCachedProcessedImageGL->getHeight() != VOAVATAR_SCRATCH_TEX_HEIGHT) ) | ||
2194 | { | ||
2195 | if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) | ||
2196 | { | ||
2197 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); | ||
2198 | |||
2199 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2200 | |||
2201 | mCachedProcessedImageGL->bind(); | ||
2202 | mCachedProcessedImageGL->setClamp(TRUE, TRUE); | ||
2203 | |||
2204 | gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight ); | ||
2205 | gl_rect_2d_simple_tex( width, height ); | ||
2206 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
2207 | mCachedProcessedImageGL->destroyGLTexture(); | ||
2208 | } | ||
2209 | else | ||
2210 | { | ||
2211 | // Create the GL texture, bind it and draw a rect, and then immediately destroy it. | ||
2212 | mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); | ||
2213 | |||
2214 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2215 | |||
2216 | mCachedProcessedImageGL->bind(); | ||
2217 | mCachedProcessedImageGL->setClamp(TRUE, TRUE); | ||
2218 | |||
2219 | gl_rect_2d_simple_tex( width, height ); | ||
2220 | |||
2221 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
2222 | |||
2223 | mCachedProcessedImageGL->destroyGLTexture(); | ||
2224 | } | ||
2225 | stop_glerror(); | ||
2226 | } | ||
2227 | else | ||
2228 | { | ||
2229 | if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) | ||
2230 | { | ||
2231 | // Write into a pre-existing GL Image, and then bind and render that. | ||
2232 | // Faster than creating a new GL Image and then destroying it. | ||
2233 | if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_COLOR_INDEX ) ) | ||
2234 | { | ||
2235 | glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, | ||
2236 | mCachedProcessedImageGL->getWidth(), | ||
2237 | mCachedProcessedImageGL->getHeight(), | ||
2238 | GL_COLOR_INDEX, GL_UNSIGNED_BYTE, | ||
2239 | mStaticImageRaw->getData() ); | ||
2240 | stop_glerror(); | ||
2241 | |||
2242 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2243 | gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight ); | ||
2244 | gl_rect_2d_simple_tex( width, height ); | ||
2245 | |||
2246 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
2247 | } | ||
2248 | else | ||
2249 | { | ||
2250 | success = FALSE; | ||
2251 | } | ||
2252 | } | ||
2253 | else | ||
2254 | { | ||
2255 | // Write into a pre-existing GL Image, and then bind and render that. | ||
2256 | // Faster than creating a new GL Image and then destroying it. | ||
2257 | if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_ALPHA ) ) | ||
2258 | { | ||
2259 | glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, | ||
2260 | mCachedProcessedImageGL->getWidth(), | ||
2261 | mCachedProcessedImageGL->getHeight(), | ||
2262 | GL_ALPHA, GL_UNSIGNED_BYTE, | ||
2263 | mStaticImageRaw->getData() ); | ||
2264 | stop_glerror(); | ||
2265 | |||
2266 | LLGLSNoAlphaTest gls_no_alpha_test; | ||
2267 | gl_rect_2d_simple_tex( width, height ); | ||
2268 | |||
2269 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
2270 | } | ||
2271 | else | ||
2272 | { | ||
2273 | success = FALSE; | ||
2274 | } | ||
2275 | } | ||
2276 | } | ||
2277 | } | ||
2278 | } | ||
2279 | |||
2280 | // Don't keep the cache for other people's avatars | ||
2281 | // (It's not really a "cache" in that case, but the logic is the same) | ||
2282 | if( !mTexLayer->getTexLayerSet()->getAvatar()->mIsSelf ) | ||
2283 | { | ||
2284 | mCachedProcessedImageGL = NULL; | ||
2285 | } | ||
2286 | } | ||
2287 | else | ||
2288 | { | ||
2289 | LLGLSNoTextureNoAlphaTest gls_no_texture_no_alpha_test; | ||
2290 | glColor4f( 0.f, 0.f, 0.f, effective_weight ); | ||
2291 | gl_rect_2d_simple( width, height ); | ||
2292 | } | ||
2293 | |||
2294 | return success; | ||
2295 | } | ||
2296 | |||
2297 | //----------------------------------------------------------------------------- | ||
2298 | // LLTexGlobalColorInfo | ||
2299 | //----------------------------------------------------------------------------- | ||
2300 | |||
2301 | LLTexGlobalColorInfo::LLTexGlobalColorInfo() | ||
2302 | { | ||
2303 | } | ||
2304 | |||
2305 | |||
2306 | LLTexGlobalColorInfo::~LLTexGlobalColorInfo() | ||
2307 | { | ||
2308 | for_each(mColorInfoList.begin(), mColorInfoList.end(), DeletePointer()); | ||
2309 | } | ||
2310 | |||
2311 | BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) | ||
2312 | { | ||
2313 | // name attribute | ||
2314 | static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); | ||
2315 | if( !node->getFastAttributeString( name_string, mName ) ) | ||
2316 | { | ||
2317 | llwarns << "<global_color> element is missing name attribute." << llendl; | ||
2318 | return FALSE; | ||
2319 | } | ||
2320 | // <param> sub-element | ||
2321 | for (LLXmlTreeNode* child = node->getChildByName( "param" ); | ||
2322 | child; | ||
2323 | child = node->getNextNamedChild()) | ||
2324 | { | ||
2325 | if( child->getChildByName( "param_color" ) ) | ||
2326 | { | ||
2327 | // <param><param_color/></param> | ||
2328 | LLTexParamColorInfo* info = new LLTexParamColorInfo(); | ||
2329 | if (!info->parseXml(child)) | ||
2330 | { | ||
2331 | delete info; | ||
2332 | return FALSE; | ||
2333 | } | ||
2334 | mColorInfoList.push_back( info ); | ||
2335 | } | ||
2336 | } | ||
2337 | return TRUE; | ||
2338 | } | ||
2339 | |||
2340 | //----------------------------------------------------------------------------- | ||
2341 | // LLTexGlobalColor | ||
2342 | //----------------------------------------------------------------------------- | ||
2343 | |||
2344 | LLTexGlobalColor::LLTexGlobalColor( LLVOAvatar* avatar ) | ||
2345 | : | ||
2346 | mAvatar( avatar ), | ||
2347 | mInfo( NULL ) | ||
2348 | { | ||
2349 | } | ||
2350 | |||
2351 | |||
2352 | LLTexGlobalColor::~LLTexGlobalColor() | ||
2353 | { | ||
2354 | // mParamList are LLViewerVisualParam's and get deleted with ~LLCharacter() | ||
2355 | //std::for_each(mParamList.begin(), mParamList.end(), DeletePointer()); | ||
2356 | } | ||
2357 | |||
2358 | BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) | ||
2359 | { | ||
2360 | llassert(mInfo == NULL); | ||
2361 | mInfo = info; | ||
2362 | //mID = info->mID; // No ID | ||
2363 | |||
2364 | LLTexGlobalColorInfo::color_info_list_t::iterator iter; | ||
2365 | mParamList.reserve(mInfo->mColorInfoList.size()); | ||
2366 | for (iter = mInfo->mColorInfoList.begin(); iter != mInfo->mColorInfoList.end(); iter++) | ||
2367 | { | ||
2368 | LLTexParamColor* param_color = new LLTexParamColor( this ); | ||
2369 | if (!param_color->setInfo(*iter)) | ||
2370 | { | ||
2371 | mInfo = NULL; | ||
2372 | return FALSE; | ||
2373 | } | ||
2374 | mParamList.push_back( param_color ); | ||
2375 | } | ||
2376 | |||
2377 | return TRUE; | ||
2378 | } | ||
2379 | |||
2380 | //----------------------------------------------------------------------------- | ||
2381 | |||
2382 | LLColor4 LLTexGlobalColor::getColor() | ||
2383 | { | ||
2384 | // Sum of color params | ||
2385 | if( !mParamList.empty() ) | ||
2386 | { | ||
2387 | LLColor4 net_color( 0.f, 0.f, 0.f, 0.f ); | ||
2388 | |||
2389 | for( param_list_t::iterator iter = mParamList.begin(); | ||
2390 | iter != mParamList.end(); iter++ ) | ||
2391 | { | ||
2392 | LLTexParamColor* param = *iter; | ||
2393 | LLColor4 param_net = param->getNetColor(); | ||
2394 | switch( param->getOperation() ) | ||
2395 | { | ||
2396 | case OP_ADD: | ||
2397 | net_color += param_net; | ||
2398 | break; | ||
2399 | case OP_MULTIPLY: | ||
2400 | net_color.mV[VX] *= param_net.mV[VX]; | ||
2401 | net_color.mV[VY] *= param_net.mV[VY]; | ||
2402 | net_color.mV[VZ] *= param_net.mV[VZ]; | ||
2403 | net_color.mV[VW] *= param_net.mV[VW]; | ||
2404 | break; | ||
2405 | case OP_BLEND: | ||
2406 | net_color = lerp(net_color, param_net, param->getWeight()); | ||
2407 | break; | ||
2408 | default: | ||
2409 | llassert(0); | ||
2410 | break; | ||
2411 | } | ||
2412 | } | ||
2413 | |||
2414 | net_color.mV[VX] = llclampf( net_color.mV[VX] ); | ||
2415 | net_color.mV[VY] = llclampf( net_color.mV[VY] ); | ||
2416 | net_color.mV[VZ] = llclampf( net_color.mV[VZ] ); | ||
2417 | net_color.mV[VW] = llclampf( net_color.mV[VW] ); | ||
2418 | |||
2419 | return net_color; | ||
2420 | } | ||
2421 | return LLColor4( 1.f, 1.f, 1.f, 1.f ); | ||
2422 | } | ||
2423 | |||
2424 | //----------------------------------------------------------------------------- | ||
2425 | // LLTexParamColorInfo | ||
2426 | //----------------------------------------------------------------------------- | ||
2427 | LLTexParamColorInfo::LLTexParamColorInfo() | ||
2428 | : | ||
2429 | mOperation( OP_ADD ), | ||
2430 | mNumColors( 0 ) | ||
2431 | { | ||
2432 | } | ||
2433 | |||
2434 | BOOL LLTexParamColorInfo::parseXml(LLXmlTreeNode *node) | ||
2435 | { | ||
2436 | llassert( node->hasName( "param" ) && node->getChildByName( "param_color" ) ); | ||
2437 | |||
2438 | if (!LLViewerVisualParamInfo::parseXml(node)) | ||
2439 | return FALSE; | ||
2440 | |||
2441 | LLXmlTreeNode* param_color_node = node->getChildByName( "param_color" ); | ||
2442 | if( !param_color_node ) | ||
2443 | { | ||
2444 | return FALSE; | ||
2445 | } | ||
2446 | |||
2447 | LLString op_string; | ||
2448 | static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); | ||
2449 | if( param_color_node->getFastAttributeString( operation_string, op_string ) ) | ||
2450 | { | ||
2451 | LLString::toLower(op_string); | ||
2452 | if ( op_string == "add" ) mOperation = OP_ADD; | ||
2453 | else if ( op_string == "multiply" ) mOperation = OP_MULTIPLY; | ||
2454 | else if ( op_string == "blend" ) mOperation = OP_BLEND; | ||
2455 | } | ||
2456 | |||
2457 | mNumColors = 0; | ||
2458 | |||
2459 | LLColor4U color4u; | ||
2460 | for (LLXmlTreeNode* child = param_color_node->getChildByName( "value" ); | ||
2461 | child; | ||
2462 | child = param_color_node->getNextNamedChild()) | ||
2463 | { | ||
2464 | if( (mNumColors < MAX_COLOR_VALUES) ) | ||
2465 | { | ||
2466 | static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); | ||
2467 | if( child->getFastAttributeColor4U( color_string, color4u ) ) | ||
2468 | { | ||
2469 | mColors[ mNumColors ].setVec(color4u); | ||
2470 | mNumColors++; | ||
2471 | } | ||
2472 | } | ||
2473 | } | ||
2474 | if( !mNumColors ) | ||
2475 | { | ||
2476 | llwarns << "<param_color> is missing <value> sub-elements" << llendl; | ||
2477 | return FALSE; | ||
2478 | } | ||
2479 | |||
2480 | if( (mOperation == OP_BLEND) && (mNumColors != 1) ) | ||
2481 | { | ||
2482 | llwarns << "<param_color> with operation\"blend\" must have exactly one <value>" << llendl; | ||
2483 | return FALSE; | ||
2484 | } | ||
2485 | |||
2486 | return TRUE; | ||
2487 | } | ||
2488 | |||
2489 | //----------------------------------------------------------------------------- | ||
2490 | // LLTexParamColor | ||
2491 | //----------------------------------------------------------------------------- | ||
2492 | LLTexParamColor::LLTexParamColor( LLTexGlobalColor* tex_global_color ) | ||
2493 | : | ||
2494 | mAvgDistortionVec(1.f, 1.f, 1.f), | ||
2495 | mTexGlobalColor( tex_global_color ), | ||
2496 | mTexLayer( NULL ), | ||
2497 | mAvatar( tex_global_color->getAvatar() ) | ||
2498 | { | ||
2499 | } | ||
2500 | |||
2501 | LLTexParamColor::LLTexParamColor( LLTexLayer* layer ) | ||
2502 | : | ||
2503 | mAvgDistortionVec(1.f, 1.f, 1.f), | ||
2504 | mTexGlobalColor( NULL ), | ||
2505 | mTexLayer( layer ), | ||
2506 | mAvatar( layer->getTexLayerSet()->getAvatar() ) | ||
2507 | { | ||
2508 | } | ||
2509 | |||
2510 | |||
2511 | LLTexParamColor::~LLTexParamColor() | ||
2512 | { | ||
2513 | } | ||
2514 | |||
2515 | //----------------------------------------------------------------------------- | ||
2516 | // setInfo() | ||
2517 | //----------------------------------------------------------------------------- | ||
2518 | |||
2519 | BOOL LLTexParamColor::setInfo(LLTexParamColorInfo *info) | ||
2520 | { | ||
2521 | llassert(mInfo == NULL); | ||
2522 | if (info->mID < 0) | ||
2523 | return FALSE; | ||
2524 | mID = info->mID; | ||
2525 | mInfo = info; | ||
2526 | |||
2527 | mAvatar->addVisualParam( this ); | ||
2528 | setWeight( getDefaultWeight(), FALSE ); | ||
2529 | |||
2530 | return TRUE; | ||
2531 | } | ||
2532 | |||
2533 | LLColor4 LLTexParamColor::getNetColor() | ||
2534 | { | ||
2535 | llassert( getInfo()->mNumColors >= 1 ); | ||
2536 | |||
2537 | F32 effective_weight = ( mAvatar && (mAvatar->getSex() & getSex()) ) ? mCurWeight : getDefaultWeight(); | ||
2538 | |||
2539 | S32 index_last = getInfo()->mNumColors - 1; | ||
2540 | F32 scaled_weight = effective_weight * index_last; | ||
2541 | S32 index_start = (S32) scaled_weight; | ||
2542 | S32 index_end = index_start + 1; | ||
2543 | if( index_start == index_last ) | ||
2544 | { | ||
2545 | return getInfo()->mColors[index_last]; | ||
2546 | } | ||
2547 | else | ||
2548 | { | ||
2549 | F32 weight = scaled_weight - index_start; | ||
2550 | const LLColor4 *start = &getInfo()->mColors[ index_start ]; | ||
2551 | const LLColor4 *end = &getInfo()->mColors[ index_end ]; | ||
2552 | return LLColor4( | ||
2553 | (1.f - weight) * start->mV[VX] + weight * end->mV[VX], | ||
2554 | (1.f - weight) * start->mV[VY] + weight * end->mV[VY], | ||
2555 | (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], | ||
2556 | (1.f - weight) * start->mV[VW] + weight * end->mV[VW] ); | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2560 | void LLTexParamColor::setWeight(F32 weight, BOOL set_by_user) | ||
2561 | { | ||
2562 | if (mIsAnimating) | ||
2563 | { | ||
2564 | return; | ||
2565 | } | ||
2566 | F32 min_weight = getMinWeight(); | ||
2567 | F32 max_weight = getMaxWeight(); | ||
2568 | F32 new_weight = llclamp(weight, min_weight, max_weight); | ||
2569 | U8 cur_u8 = F32_to_U8( mCurWeight, min_weight, max_weight ); | ||
2570 | U8 new_u8 = F32_to_U8( new_weight, min_weight, max_weight ); | ||
2571 | if( cur_u8 != new_u8) | ||
2572 | { | ||
2573 | mCurWeight = new_weight; | ||
2574 | |||
2575 | if( getInfo()->mNumColors <= 0 ) | ||
2576 | { | ||
2577 | // This will happen when we set the default weight the first time. | ||
2578 | return; | ||
2579 | } | ||
2580 | |||
2581 | if( mAvatar->getSex() & getSex() ) | ||
2582 | { | ||
2583 | if( mTexGlobalColor ) | ||
2584 | { | ||
2585 | mAvatar->onGlobalColorChanged( mTexGlobalColor, set_by_user ); | ||
2586 | } | ||
2587 | else | ||
2588 | if( mTexLayer ) | ||
2589 | { | ||
2590 | mAvatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); | ||
2591 | } | ||
2592 | } | ||
2593 | // llinfos << "param " << mName << " = " << new_weight << llendl; | ||
2594 | } | ||
2595 | } | ||
2596 | |||
2597 | void LLTexParamColor::setAnimationTarget(F32 target_value, BOOL set_by_user) | ||
2598 | { | ||
2599 | // set value first then set interpolating flag to ignore further updates | ||
2600 | mTargetWeight = target_value; | ||
2601 | setWeight(target_value, set_by_user); | ||
2602 | mIsAnimating = TRUE; | ||
2603 | if (mNext) | ||
2604 | { | ||
2605 | mNext->setAnimationTarget(target_value, set_by_user); | ||
2606 | } | ||
2607 | } | ||
2608 | |||
2609 | void LLTexParamColor::animate(F32 delta, BOOL set_by_user) | ||
2610 | { | ||
2611 | if (mNext) | ||
2612 | { | ||
2613 | mNext->animate(delta, set_by_user); | ||
2614 | } | ||
2615 | } | ||
2616 | |||
2617 | |||
2618 | //----------------------------------------------------------------------------- | ||
2619 | // LLTexStaticImageList | ||
2620 | //----------------------------------------------------------------------------- | ||
2621 | |||
2622 | // static | ||
2623 | LLTexStaticImageList gTexStaticImageList; | ||
2624 | LLStringTable LLTexStaticImageList::sImageNames(16384); | ||
2625 | |||
2626 | LLTexStaticImageList::LLTexStaticImageList() | ||
2627 | : | ||
2628 | mRawBytes( 0 ), | ||
2629 | mGLBytes( 0 ), | ||
2630 | mTGABytes( 0 ) | ||
2631 | {} | ||
2632 | |||
2633 | LLTexStaticImageList::~LLTexStaticImageList() | ||
2634 | { | ||
2635 | deleteCachedImages(); | ||
2636 | } | ||
2637 | |||
2638 | void LLTexStaticImageList::dumpByteCount() | ||
2639 | { | ||
2640 | llinfos << "Avatar Static Textures " << | ||
2641 | " Raw:" << (mRawBytes / 1024) << | ||
2642 | "KB GL:" << (mGLBytes / 1024) << | ||
2643 | "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; | ||
2644 | } | ||
2645 | |||
2646 | void LLTexStaticImageList::deleteCachedImages() | ||
2647 | { | ||
2648 | if( mRawBytes || mGLBytes || mTGABytes ) | ||
2649 | { | ||
2650 | llinfos << "Clearing Static Textures " << | ||
2651 | " Raw:" << (mRawBytes / 1024) << | ||
2652 | "KB GL:" << (mGLBytes / 1024) << | ||
2653 | "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; | ||
2654 | |||
2655 | //mStaticImageLists uses LLPointers, clear() will cause deletion | ||
2656 | |||
2657 | mStaticImageListRaw.clear(); | ||
2658 | mStaticImageListTGA.clear(); | ||
2659 | mStaticImageListGL.clear(); | ||
2660 | |||
2661 | mRawBytes = 0; | ||
2662 | mGLBytes = 0; | ||
2663 | mTGABytes = 0; | ||
2664 | } | ||
2665 | } | ||
2666 | |||
2667 | // Note: in general, for a given image image we'll call either getImageTga(), getImageRaw() or getImageGL(). | ||
2668 | // We call getImageTga() if the image is used as an alpha gradient. | ||
2669 | // Otherwise, we call getImageRaw() if we have 32 MB or less of video RAM or less and getImageGL() if we have | ||
2670 | // more video RAM than that. | ||
2671 | |||
2672 | // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. | ||
2673 | // Caches the result to speed identical subsequent requests. | ||
2674 | LLImageTGA* LLTexStaticImageList::getImageTGA(const LLString& file_name) | ||
2675 | { | ||
2676 | const char *namekey = sImageNames.addString(file_name); | ||
2677 | image_tga_map_t::iterator iter = mStaticImageListTGA.find(namekey); | ||
2678 | if( iter != mStaticImageListTGA.end() ) | ||
2679 | { | ||
2680 | return iter->second; | ||
2681 | } | ||
2682 | else | ||
2683 | { | ||
2684 | std::string path; | ||
2685 | path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str()); | ||
2686 | LLPointer<LLImageTGA> image_tga = new LLImageTGA( path ); | ||
2687 | if( image_tga->getDataSize() > 0 ) | ||
2688 | { | ||
2689 | mStaticImageListTGA[ namekey ] = image_tga; | ||
2690 | mTGABytes += image_tga->getDataSize(); | ||
2691 | return image_tga; | ||
2692 | } | ||
2693 | else | ||
2694 | { | ||
2695 | return NULL; | ||
2696 | } | ||
2697 | } | ||
2698 | } | ||
2699 | |||
2700 | |||
2701 | |||
2702 | // Returns an LLImageRaw that contains the decoded data from a tga file named file_name. | ||
2703 | // Caches the result to speed identical subsequent requests. | ||
2704 | LLImageRaw* LLTexStaticImageList::getImageRaw(const LLString& file_name) | ||
2705 | { | ||
2706 | LLPointer<LLImageRaw> image_raw; | ||
2707 | const char *namekey = sImageNames.addString(file_name); | ||
2708 | image_raw_map_t::iterator iter = mStaticImageListRaw.find(namekey); | ||
2709 | if( iter != mStaticImageListRaw.end() ) | ||
2710 | { | ||
2711 | image_raw = iter->second; | ||
2712 | } | ||
2713 | else | ||
2714 | { | ||
2715 | image_raw = new LLImageRaw(); | ||
2716 | if( loadImageRaw( file_name, image_raw ) ) | ||
2717 | { | ||
2718 | mStaticImageListRaw[ namekey ] = image_raw; | ||
2719 | mRawBytes += image_raw->getDataSize(); | ||
2720 | } | ||
2721 | else | ||
2722 | { | ||
2723 | image_raw = NULL; | ||
2724 | } | ||
2725 | } | ||
2726 | |||
2727 | return image_raw; | ||
2728 | } | ||
2729 | |||
2730 | // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. | ||
2731 | // Caches the result to speed identical subsequent requests. | ||
2732 | LLImageGL* LLTexStaticImageList::getImageGL(const LLString& file_name, BOOL is_mask ) | ||
2733 | { | ||
2734 | LLPointer<LLImageGL> image_gl; | ||
2735 | const char *namekey = sImageNames.addString(file_name); | ||
2736 | |||
2737 | image_gl_map_t::iterator iter = mStaticImageListGL.find(namekey); | ||
2738 | if( iter != mStaticImageListGL.end() ) | ||
2739 | { | ||
2740 | image_gl = iter->second; | ||
2741 | } | ||
2742 | else | ||
2743 | { | ||
2744 | image_gl = new LLImageGL( FALSE ); | ||
2745 | LLPointer<LLImageRaw> image_raw = new LLImageRaw; | ||
2746 | if( loadImageRaw( file_name, image_raw ) ) | ||
2747 | { | ||
2748 | if( (image_raw->getComponents() == 1) && is_mask ) | ||
2749 | { | ||
2750 | // Note: these are static, unchanging images so it's ok to assume | ||
2751 | // that once an image is a mask it's always a mask. | ||
2752 | image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); | ||
2753 | } | ||
2754 | image_gl->createGLTexture(0, image_raw); | ||
2755 | |||
2756 | image_gl->bind(); | ||
2757 | image_gl->setClamp(TRUE, TRUE); | ||
2758 | |||
2759 | mStaticImageListGL [ namekey ] = image_gl; | ||
2760 | mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); | ||
2761 | } | ||
2762 | else | ||
2763 | { | ||
2764 | image_gl = NULL; | ||
2765 | } | ||
2766 | } | ||
2767 | |||
2768 | return image_gl; | ||
2769 | } | ||
2770 | |||
2771 | // Reads a .tga file, decodes it, and puts the decoded data in image_raw. | ||
2772 | // Returns TRUE if successful. | ||
2773 | BOOL LLTexStaticImageList::loadImageRaw( const LLString& file_name, LLImageRaw* image_raw ) | ||
2774 | { | ||
2775 | BOOL success = FALSE; | ||
2776 | std::string path; | ||
2777 | path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name.c_str()); | ||
2778 | LLPointer<LLImageTGA> image_tga = new LLImageTGA( path ); | ||
2779 | if( image_tga->getDataSize() > 0 ) | ||
2780 | { | ||
2781 | // Copy data from tga to raw. | ||
2782 | success = image_tga->decode( image_raw ); | ||
2783 | } | ||
2784 | |||
2785 | return success; | ||
2786 | } | ||
2787 | |||
2788 | //----------------------------------------------------------------------------- | ||
2789 | // LLMaskedMorph() | ||
2790 | //----------------------------------------------------------------------------- | ||
2791 | LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert) | ||
2792 | { | ||
2793 | morph_target->addPendingMorphMask(); | ||
2794 | } | ||
2795 | |||
2796 | |||
2797 | //----------------------------------------------------------------------------- | ||
2798 | // LLGradientPaletteList | ||
2799 | //----------------------------------------------------------------------------- | ||
2800 | |||
2801 | LLGradientPaletteList::~LLGradientPaletteList() | ||
2802 | { | ||
2803 | // Note: can't just call deleteAllData() because the data values are arrays. | ||
2804 | for( palette_map_t::iterator iter = mPaletteMap.begin(); | ||
2805 | iter != mPaletteMap.end(); iter++ ) | ||
2806 | { | ||
2807 | U8* data = iter->second; | ||
2808 | delete []data; | ||
2809 | } | ||
2810 | } | ||
2811 | |||
2812 | void LLGradientPaletteList::initPalette(F32 domain) | ||
2813 | { | ||
2814 | palette_map_t::iterator iter = mPaletteMap.find( domain ); | ||
2815 | if( iter == mPaletteMap.end() ) | ||
2816 | { | ||
2817 | U8 *palette = new U8[512 * 4]; | ||
2818 | mPaletteMap[domain] = palette; | ||
2819 | S32 ramp_start = 255 - llfloor(domain * 255.f); | ||
2820 | S32 ramp_end = 255; | ||
2821 | F32 ramp_factor = (ramp_end == ramp_start) ? 0.f : (255.f / ((F32)ramp_end - (F32)ramp_start)); | ||
2822 | |||
2823 | // *TODO: move conditionals outside of loop, since this really | ||
2824 | // is just a sequential process. | ||
2825 | for (S32 i = 0; i < 512; i++) | ||
2826 | { | ||
2827 | palette[(i * 4) + 1] = 0; | ||
2828 | palette[(i * 4) + 2] = 0; | ||
2829 | if (i <= ramp_start) | ||
2830 | { | ||
2831 | palette[(i * 4)] = 0; | ||
2832 | palette[(i * 4) + 3] = 0; | ||
2833 | } | ||
2834 | else if (i < ramp_end) | ||
2835 | { | ||
2836 | palette[(i * 4)] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor); | ||
2837 | palette[(i * 4) + 3] = llfloor(((F32)i - (F32)ramp_start) * ramp_factor); | ||
2838 | } | ||
2839 | else | ||
2840 | { | ||
2841 | palette[(i * 4)] = 255; | ||
2842 | palette[(i * 4) + 3] = 255; | ||
2843 | } | ||
2844 | } | ||
2845 | } | ||
2846 | } | ||
2847 | |||
2848 | void LLGradientPaletteList::setHardwarePalette( F32 domain, F32 effective_weight ) | ||
2849 | { | ||
2850 | palette_map_t::iterator iter = mPaletteMap.find( domain ); | ||
2851 | if( iter != mPaletteMap.end() ) | ||
2852 | { | ||
2853 | U8* palette = iter->second; | ||
2854 | set_palette( palette + llfloor(effective_weight * (255.f * (1.f - domain))) * 4); | ||
2855 | } | ||
2856 | else | ||
2857 | { | ||
2858 | llwarns << "LLGradientPaletteList::setHardwarePalette() missing domain " << domain << llendl; | ||
2859 | } | ||
2860 | } | ||