Ptex: PtexReader.cpp Source File

Ptex

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

PtexReader.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2009 Disney Enterprises, Inc. All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18 Studios" or the names of its contributors may NOT be used to
19 endorse or promote products derived from this software without
20 specific prior written permission from Walt Disney Pictures.
21
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
35
36 #include "PtexPlatform.h"
37 #include <iostream>
38 #include <sstream>
39 #include <stdio.h>
40
41 #include "Ptexture.h"
42 #include "PtexUtils.h"
43 #include "PtexReader.h"
44
45
46 PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
47 {
48 // create a private cache and use it to open the file
49 PtexCache* cache = PtexCache::create(1, 1024*1024, premultiply);
50 PtexTexture* file = cache->get(path, error);
51
52 // make reader own the cache (so it will delete it later)
53 // Note: we know that we have a PtexReader because it came from the cache
54 PtexReader* reader = static_cast<PtexReader*> (file);
55 if (reader) reader->setOwnsCache();
56
57 // and purge cache so cache doesn't try to hold reader open
58 cache->purgeAll();
59 return file;
60 }
61
62
63 bool PtexReader::open(const char* path, Ptex::String& error)
64 {
65 if (!LittleEndian()) {
66 error = "Ptex library doesn't currently support big-endian cpu's";
67 return 0;
68 }
69 _path = path;
70 _fp = _io->open(path);
71 if (!_fp) {
72 std::string errstr = "Can't open ptex file: ";
73 errstr += path; errstr += "\n"; errstr += _io->lastError();
74 error = errstr.c_str();
75 return 0;
76 }
77 readBlock(&_header, HeaderSize);
78 if (_header.magic != Magic) {
79 std::string errstr = "Not a ptex file: "; errstr += path;
80 error = errstr.c_str();
81 return 0;
82 }
83 if (_header.version != 1) {
84 std::stringstream s;
85 s << "Unsupported ptex file version ("<< _header.version << "): " << path;
86 error = s.str();
87 return 0;
88 }
89 _pixelsize = _header.pixelSize();
90
91 // read extended header
92 memset(&_extheader, 0, sizeof(_extheader));
93 readBlock(&_extheader, PtexUtils::min(uint32_t(ExtHeaderSize), _header.extheadersize));
94
95 // compute offsets of various blocks
96 FilePos pos = HeaderSize + _header.extheadersize;
97 _faceinfopos = pos; pos += _header.faceinfosize;
98 _constdatapos = pos; pos += _header.constdatasize;
99 _levelinfopos = pos; pos += _header.levelinfosize;
100 _leveldatapos = pos; pos += _header.leveldatasize;
101 _metadatapos = pos; pos += _header.metadatazipsize;
102 pos += sizeof(uint64_t); // compatibility barrier
103 _lmdheaderpos = pos; pos += _extheader.lmdheaderzipsize;
104 _lmddatapos = pos; pos += _extheader.lmddatasize;
105
106 // edit data may not start immediately if additional sections have been added
107 // use value from extheader if present (and > pos)
108 _editdatapos = PtexUtils::max(FilePos(_extheader.editdatapos), pos);
109
110 // read basic file info
111 readFaceInfo();
112 readConstData();
113 readLevelInfo();
114 readEditData();
115
116 // an error occurred while reading the file
117 if (!_ok) {
118 error = _error.c_str();
119 return 0;
120 }
121
122 return 1;
123 }
124
125
126 PtexReader::PtexReader(void** parent, PtexCacheImpl* cache, bool premultiply,
127 PtexInputHandler* io)
128 : PtexCachedFile(parent, cache),
129 _io(io ? io : &_defaultIo),
130 _premultiply(premultiply),
131 _ownsCache(false),
132 _ok(true),
133 _fp(0),
134 _pos(0),
135 _pixelsize(0),
136 _constdata(0),
137 _metadata(0),
138 _hasEdits(false)
139 {
140 memset(&_header, 0, sizeof(_header));
141 memset(&_zstream, 0, sizeof(_zstream));
142 inflateInit(&_zstream);
143 }
144
145
146 PtexReader::~PtexReader()
147 {
148 if (_fp) _io->close(_fp);
149
150 // we can free the const data directly since we own it (it doesn't go through the cache)
151 if (_constdata) free(_constdata);
152
153 // the rest must be orphaned since there may still be references outstanding
154 orphanList(_levels);
155 for (ReductionMap::iterator i = _reductions.begin(); i != _reductions.end(); i++) {
156 FaceData* f = (*i).second;
157 if (f) f->orphan();
158 }
159 if (_metadata) {
160 _metadata->orphan();
161 _metadata = 0;
162 }
163
164 inflateEnd(&_zstream);
165
166 if (_ownsCache) _cache->setPendingDelete();
167 }
168
169
170 void PtexReader::release()
171 {
172 PtexCacheImpl* cache = _cache;
173 {
174 // create local scope for cache lock
175 AutoLockCache lock(cache->cachelock);
176 unref();
177 }
178 // If this reader owns the cache, then releasing it may cause deletion of the
179 // reader and thus flag the cache for pending deletion. Call the cache
180 // to handle the pending deletion.
181 cache->handlePendingDelete();
182 }
183
184
185 const Ptex::FaceInfo& PtexReader::getFaceInfo(int faceid)
186 {
187 if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
188 return _faceinfo[faceid];
189
190 static Ptex::FaceInfo dummy;
191 return dummy;
192 }
193
194
195 void PtexReader::readFaceInfo()
196 {
197 if (_faceinfo.empty()) {
198 // read compressed face info block
199 seek(_faceinfopos);
200 int nfaces = _header.nfaces;
201 _faceinfo.resize(nfaces);
202 readZipBlock(&_faceinfo[0], _header.faceinfosize,
203 (int)(sizeof(FaceInfo)*nfaces));
204
205 // generate rfaceids
206 _rfaceids.resize(nfaces);
207 std::vector<uint32_t> faceids_r(nfaces);
208 PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
209 &_rfaceids[0], &faceids_r[0]);
210
211 // store face res values indexed by rfaceid
212 _res_r.resize(nfaces);
213 for (int i = 0; i < nfaces; i++)
214 _res_r[i] = _faceinfo[faceids_r[i]].res;
215 }
216 }
217
218
219
220 void PtexReader::readLevelInfo()
221 {
222 if (_levelinfo.empty()) {
223 // read level info block
224 seek(_levelinfopos);
225 _levelinfo.resize(_header.nlevels);
226 readBlock(&_levelinfo[0], LevelInfoSize*_header.nlevels);
227
228 // initialize related data
229 _levels.resize(_header.nlevels);
230 _levelpos.resize(_header.nlevels);
231 FilePos pos = _leveldatapos;
232 for (int i = 0; i < _header.nlevels; i++) {
233 _levelpos[i] = pos;
234 pos += _levelinfo[i].leveldatasize;
235 }
236 }
237 }
238
239
240 void PtexReader::readConstData()
241 {
242 if (!_constdata) {
243 // read compressed constant data block
244 seek(_constdatapos);
245 int size = _pixelsize * _header.nfaces;
246 _constdata = (uint8_t*) malloc(size);
247 readZipBlock(_constdata, _header.constdatasize, size);
248 if (_premultiply && _header.hasAlpha())
249 PtexUtils::multalpha(_constdata, _header.nfaces, _header.datatype,
250 _header.nchannels, _header.alphachan);
251 }
252 }
253
254
255 PtexMetaData* PtexReader::getMetaData()
256 {
257 AutoLockCache locker(_cache->cachelock);
258 if (_metadata) _metadata->ref();
259 else readMetaData();
260 return _metadata;
261 }
262
263
264 PtexReader::MetaData::Entry*
265 PtexReader::MetaData::getEntry(const char* key)
266 {
267 MetaMap::iterator iter = _map.find(key);
268 if (iter == _map.end()) {
269 // not found
270 return 0;
271 }
272
273 Entry* e = &iter->second;
274 if (!e->isLmd) {
275 // normal (small) meta data - just return directly
276 return e;
277 }
278
279 // large meta data - may not be read in yet
280 AutoLockCache lock(_cache->cachelock);
281 if (e->lmdData) {
282 // already in memory, add a ref
283 e->lmdData->ref();
284 _lmdRefs.push_back(e->lmdData);
285 return e;
286 }
287 else {
288 // not present, must read from file
289 // temporarily release cache lock so other threads can proceed
290 _cache->cachelock.unlock();
291
292 // get read lock and make sure we still need to read
293 AutoMutex locker(_reader->readlock);
294 if (e->lmdData) {
295 // another thread must have read it while we were waiting
296 _cache->cachelock.lock();
297
298 // make sure it's still there now that we have the lock
299 if (e->lmdData) {
300 e->data = e->lmdData->data();
301 _lmdRefs.push_back(e->lmdData);
302 e->lmdData->ref();
303 return e;
304 }
305 }
306 // go ahead and read, keep local until finished
307 LargeMetaData*& parent = e->lmdData;
308 LargeMetaData* volatile lmdData = new LargeMetaData((void**)&parent, _cache, e->datasize);
309 e->data = lmdData->data();
310 _reader->seek(e->lmdPos);
311 _reader->readZipBlock(e->data, e->lmdZipSize, e->datasize);
312 // reacquire cache lock and update entry
313 _cache->cachelock.lock();
314 e->lmdData = lmdData;
315 return e;
316 }
317 }
318
319
320 void PtexReader::readMetaData()
321 {
322 // temporarily release cache lock so other threads can proceed
323 _cache->cachelock.unlock();
324
325 // get read lock and make sure we still need to read
326 AutoMutex locker(readlock);
327 if (_metadata) {
328 // another thread must have read it while we were waiting
329 _cache->cachelock.lock();
330 // make sure it's still there now that we have the lock
331 if (_metadata) {
332 _metadata->ref();
333 return;
334 }
335 _cache->cachelock.unlock();
336 }
337
338
339 // compute total size (including edit blocks) for cache tracking
340 int totalsize = _header.metadatamemsize;
341 for (size_t i = 0, size = _metaedits.size(); i < size; i++)
342 totalsize += _metaedits[i].memsize;
343
344 // allocate new meta data (keep local until fully initialized)
345 MetaData* volatile newmeta = new MetaData(&_metadata, _cache, totalsize, this);
346
347 // read primary meta data blocks
348 if (_header.metadatamemsize)
349 readMetaDataBlock(newmeta, _metadatapos,
350 _header.metadatazipsize, _header.metadatamemsize);
351
352 // read large meta data headers
353 if (_extheader.lmdheadermemsize)
354 readLargeMetaDataHeaders(newmeta, _lmdheaderpos,
355 _extheader.lmdheaderzipsize, _extheader.lmdheadermemsize);
356
357 // read meta data edits
358 for (size_t i = 0, size = _metaedits.size(); i < size; i++)
359 readMetaDataBlock(newmeta, _metaedits[i].pos,
360 _metaedits[i].zipsize, _metaedits[i].memsize);
361
362 // store meta data
363 _cache->cachelock.lock();
364 _metadata = newmeta;
365
366 // clean up unused data
367 _cache->purgeData();
368 }
369
370
371 void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize)
372 {
373 seek(pos);
374 // read from file
375 bool useMalloc = memsize > AllocaMax;
376 char* buff = useMalloc ? (char*) malloc(memsize) : (char*)alloca(memsize);
377
378 if (readZipBlock(buff, zipsize, memsize)) {
379 // unpack data entries
380 char* ptr = buff;
381 char* end = ptr + memsize;
382 while (ptr < end) {
383 uint8_t keysize = *ptr++;
384 char* key = (char*)ptr; ptr += keysize;
385 key[keysize-1] = '\0';
386 uint8_t datatype = *ptr++;
387 uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
388 ptr += sizeof(datasize);
389 char* data = ptr; ptr += datasize;
390 metadata->addEntry((uint8_t)(keysize-1), key, datatype, datasize, data);
391 }
392 }
393 if (useMalloc) free(buff);
394 }
395
396
397 void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize)
398 {
399 seek(pos);
400 // read from file
401 bool useMalloc = memsize > AllocaMax;
402 char* buff = useMalloc ? (char*) malloc(memsize) : (char*)alloca(memsize);
403
404 if (readZipBlock(buff, zipsize, memsize)) {
405 pos += zipsize;
406
407 // unpack data entries
408 char* ptr = buff;
409 char* end = ptr + memsize;
410 while (ptr < end) {
411 uint8_t keysize = *ptr++;
412 char* key = (char*)ptr; ptr += keysize;
413 uint8_t datatype = *ptr++;
414 uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
415 ptr += sizeof(datasize);
416 uint32_t zipsize; memcpy(&zipsize, ptr, sizeof(zipsize));
417 ptr += sizeof(zipsize);
418 metadata->addLmdEntry((uint8_t)(keysize-1), key, datatype, datasize, pos, zipsize);
419 pos += zipsize;
420 }
421 }
422 if (useMalloc) free(buff);
423 }
424
425 void PtexReader::readEditData()
426 {
427 // determine file range to scan for edits
428 FilePos pos = FilePos(_editdatapos), endpos;
429 if (_extheader.editdatapos > 0) {
430 // newer files record the edit data position and size in the extheader
431 // note: position will be non-zero even if size is zero
432 endpos = FilePos(pos + _extheader.editdatasize);
433 }
434 else {
435 // must have an older file, just read until EOF
436 endpos = FilePos((uint64_t)-1);
437 }
438
439 while (pos < endpos) {
440 seek(pos);
441 // read the edit data header
442 uint8_t edittype = et_editmetadata;
443 uint32_t editsize;
444 if (!readBlock(&edittype, sizeof(edittype), /*reporterror*/ false)) break;
445 if (!readBlock(&editsize, sizeof(editsize), /*reporterror*/ false)) break;
446 if (!editsize) break;
447 _hasEdits = true;
448 pos = tell() + editsize;
449 switch (edittype) {
450 case et_editfacedata: readEditFaceData(); break;
451 case et_editmetadata: readEditMetaData(); break;
452 }
453 }
454 }
455
456
457 void PtexReader::readEditFaceData()
458 {
459 // read header
460 EditFaceDataHeader efdh;
461 if (!readBlock(&efdh, EditFaceDataHeaderSize)) return;
462
463 // update face info
464 int faceid = efdh.faceid;
465 if (faceid < 0 || size_t(faceid) >= _header.nfaces) return;
466 FaceInfo& f = _faceinfo[faceid];
467 f = efdh.faceinfo;
468 f.flags |= FaceInfo::flag_hasedits;
469
470 // read const value now
471 uint8_t* constdata = _constdata + _pixelsize * faceid;
472 if (!readBlock(constdata, _pixelsize)) return;
473 if (_premultiply && _header.hasAlpha())
474 PtexUtils::multalpha(constdata, 1, _header.datatype,
475 _header.nchannels, _header.alphachan);
476
477 // update header info for remaining data
478 if (!f.isConstant()) {
479 _faceedits.push_back(FaceEdit());
480 FaceEdit& e = _faceedits.back();
481 e.pos = tell();
482 e.faceid = faceid;
483 e.fdh = efdh.fdh;
484 }
485 }
486
487
488 void PtexReader::readEditMetaData()
489 {
490 // read header
491 EditMetaDataHeader emdh;
492 if (!readBlock(&emdh, EditMetaDataHeaderSize)) return;
493
494 // record header info for later
495 _metaedits.push_back(MetaEdit());
496 MetaEdit& e = _metaedits.back();
497 e.pos = tell();
498 e.zipsize = emdh.metadatazipsize;
499 e.memsize = emdh.metadatamemsize;
500 }
501
502
503 bool PtexReader::readBlock(void* data, int size, bool reporterror)
504 {
505 int result = (int)_io->read(data, size, _fp);
506 if (result == size) {
507 _pos += size;
508 STATS_INC(nblocksRead);
509 STATS_ADD(nbytesRead, size);
510 return 1;
511 }
512 if (reporterror)
513 setError("PtexReader error: read failed (EOF)");
514 return 0;
515 }
516
517
518 bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
519 {
520 void* buff = alloca(BlockSize);
521 _zstream.next_out = (Bytef*) data;
522 _zstream.avail_out = unzipsize;
523
524 while (1) {
525 int size = (zipsize < BlockSize) ? zipsize : BlockSize;
526 zipsize -= size;
527 if (!readBlock(buff, size)) break;
528 _zstream.next_in = (Bytef*) buff;
529 _zstream.avail_in = size;
530 int zresult = inflate(&_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
531 if (zresult == Z_STREAM_END) break;
532 if (zresult != Z_OK) {
533 setError("PtexReader error: unzip failed, file corrupt");
534 inflateReset(&_zstream);
535 return 0;
536 }
537 }
538
539 int total = (int)_zstream.total_out;
540 inflateReset(&_zstream);
541 return total == unzipsize;
542 }
543
544
545 void PtexReader::readLevel(int levelid, Level*& level)
546 {
547 // temporarily release cache lock so other threads can proceed
548 _cache->cachelock.unlock();
549
550 // get read lock and make sure we still need to read
551 AutoMutex locker(readlock);
552 if (level) {
553 // another thread must have read it while we were waiting
554 _cache->cachelock.lock();
555 // make sure it's still there now that we have the lock
556 if (level) {
557 level->ref();
558 return;
559 }
560 _cache->cachelock.unlock();
561 }
562
563 // go ahead and read the level
564 LevelInfo& l = _levelinfo[levelid];
565
566 // keep new level local until finished
567 Level* volatile newlevel = new Level((void**)&level, _cache, l.nfaces);
568 seek(_levelpos[levelid]);
569 readZipBlock(&newlevel->fdh[0], l.levelheadersize, FaceDataHeaderSize * l.nfaces);
570 computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
571
572 // apply edits (if any) to level 0
573 if (levelid == 0) {
574 for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
575 FaceEdit& e = _faceedits[i];
576 newlevel->fdh[e.faceid] = e.fdh;
577 newlevel->offsets[e.faceid] = e.pos;
578 }
579 }
580
581 // don't assign to result until level data is fully initialized
582 _cache->cachelock.lock();
583 level = newlevel;
584
585 // clean up unused data
586 _cache->purgeData();
587 }
588
589
590 void PtexReader::readFace(int levelid, Level* level, int faceid)
591 {
592 // temporarily release cache lock so other threads can proceed
593 _cache->cachelock.unlock();
594
595 // get read lock and make sure we still need to read
596 FaceData*& face = level->faces[faceid];
597 AutoMutex locker(readlock);
598
599 if (face) {
600 // another thread must have read it while we were waiting
601 _cache->cachelock.lock();
602 // make sure it's still there now that we have the lock
603 if (face) {
604 face->ref();
605 return;
606 }
607 _cache->cachelock.unlock();
608 }
609
610 // Go ahead and read the face, and read nearby faces if
611 // possible. The goal is to coalesce small faces into single
612 // runs of consecutive reads to minimize seeking and take
613 // advantage of read-ahead buffering.
614
615 // Try to read as many faces as will fit in BlockSize. Use the
616 // in-memory size rather than the on-disk size to prevent flooding
617 // the memory cache. And don't coalesce w/ tiled faces as these
618 // are meant to be read individually.
619
620 // scan both backwards and forwards looking for unread faces
621 int first = faceid, last = faceid;
622 int totalsize = 0;
623
624 FaceDataHeader fdh = level->fdh[faceid];
625 if (fdh.encoding() != enc_tiled) {
626 totalsize += unpackedSize(fdh, levelid, faceid);
627
628 int nfaces = int(level->fdh.size());
629 while (1) {
630 int f = first-1;
631 if (f < 0 || level->faces[f]) break;
632 fdh = level->fdh[f];
633 if (fdh.encoding() == enc_tiled) break;
634 int size = totalsize + unpackedSize(fdh, levelid, f);
635 if (size > BlockSize) break;
636 first = f;
637 totalsize = size;
638 }
639 while (1) {
640 int f = last+1;
641 if (f >= nfaces || level->faces[f]) break;
642 fdh = level->fdh[f];
643 if (fdh.encoding() == enc_tiled) break;
644 int size = totalsize + unpackedSize(fdh, levelid, f);
645 if (size > BlockSize) break;
646 last = f;
647 totalsize = size;
648 }
649 }
650
651 // read all faces in range
652 // keep track of extra faces we read so we can add them to the cache later
653 std::vector<FaceData*> extraFaces;
654 extraFaces.reserve(last-first);
655
656 for (int i = first; i <= last; i++) {
657 fdh = level->fdh[i];
658 // skip faces with zero size (which is true for level-0 constant faces)
659 if (fdh.blocksize()) {
660 FaceData*& face = level->faces[i];
661 readFaceData(level->offsets[i], fdh, getRes(levelid, i), levelid, face);
662 if (i != faceid) extraFaces.push_back(face);
663 }
664 }
665
666 // reacquire cache lock, then unref extra faces to add them to the cache
667 _cache->cachelock.lock();
668 for (size_t i = 0, size = extraFaces.size(); i < size; i++)
669 extraFaces[i]->unref();
670 }
671
672
673 void PtexReader::TiledFace::readTile(int tile, FaceData*& data)
674 {
675 // temporarily release cache lock so other threads can proceed
676 _cache->cachelock.unlock();
677
678 // get read lock and make sure we still need to read
679 AutoMutex locker(_reader->readlock);
680 if (data) {
681 // another thread must have read it while we were waiting
682 _cache->cachelock.lock();
683 // make sure it's still there now that we have the lock
684 if (data) {
685 data->ref();
686 return;
687 }
688 _cache->cachelock.unlock();
689 }
690
691 // go ahead and read the face data
692 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
693 _cache->cachelock.lock();
694
695 // clean up unused data
696 _cache->purgeData();
697 }
698
699
700 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
701 FaceData*& face)
702 {
703 // keep new face local until fully initialized
704 FaceData* volatile newface = 0;
705
706 seek(pos);
707 switch (fdh.encoding()) {
708 case enc_constant:
709 {
710 ConstantFace* pf = new ConstantFace((void**)&face, _cache, _pixelsize);
711 readBlock(pf->data(), _pixelsize);
712 if (levelid==0 && _premultiply && _header.hasAlpha())
713 PtexUtils::multalpha(pf->data(), 1, _header.datatype,
714 _header.nchannels, _header.alphachan);
715 newface = pf;
716 }
717 break;
718 case enc_tiled:
719 {
720 Res tileres;
721 readBlock(&tileres, sizeof(tileres));
722 uint32_t tileheadersize;
723 readBlock(&tileheadersize, sizeof(tileheadersize));
724 TiledFace* tf = new TiledFace((void**)&face, _cache, res, tileres, levelid, this);
725 readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
726 computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
727 newface = tf;
728 }
729 break;
730 case enc_zipped:
731 case enc_diffzipped:
732 {
733 int uw = res.u(), vw = res.v();
734 int npixels = uw * vw;
735 int unpackedSize = _pixelsize * npixels;
736 PackedFace* pf = new PackedFace((void**)&face, _cache,
737 res, _pixelsize, unpackedSize);
738 bool useMalloc = unpackedSize > AllocaMax;
739 void* tmp = useMalloc ? malloc(unpackedSize) : alloca(unpackedSize);
740 readZipBlock(tmp, fdh.blocksize(), unpackedSize);
741 if (fdh.encoding() == enc_diffzipped)
742 PtexUtils::decodeDifference(tmp, unpackedSize, _header.datatype);
743 PtexUtils::interleave(tmp, uw * DataSize(_header.datatype), uw, vw,
744 pf->data(), uw * _pixelsize,
745 _header.datatype, _header.nchannels);
746 if (levelid==0 && _premultiply && _header.hasAlpha())
747 PtexUtils::multalpha(pf->data(), npixels, _header.datatype,
748 _header.nchannels, _header.alphachan);
749 newface = pf;
750 if (useMalloc) free(tmp);
751 }
752 break;
753 }
754
755 face = newface;
756 }
757
758
759 void PtexReader::getData(int faceid, void* buffer, int stride)
760 {
761 if (!_ok) return;
762 FaceInfo& f = _faceinfo[faceid];
763 getData(faceid, buffer, stride, f.res);
764 }
765
766
767 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
768 {
769 if (!_ok) return;
770
771 // note - all locking is handled in called getData methods
772 int resu = res.u(), resv = res.v();
773 int rowlen = _pixelsize * resu;
774 if (stride == 0) stride = rowlen;
775
776 PtexPtr<PtexFaceData> d ( getData(faceid, res) );
777 if (!d) return;
778 if (d->isConstant()) {
779 // fill dest buffer with pixel value
780 PtexUtils::fill(d->getData(), buffer, stride,
781 resu, resv, _pixelsize);
782 }
783 else if (d->isTiled()) {
784 // loop over tiles
785 Res tileres = d->tileRes();
786 int ntilesu = res.ntilesu(tileres);
787 int ntilesv = res.ntilesv(tileres);
788 int tileures = tileres.u();
789 int tilevres = tileres.v();
790 int tilerowlen = _pixelsize * tileures;
791 int tile = 0;
792 char* dsttilerow = (char*) buffer;
793 for (int i = 0; i < ntilesv; i++) {
794 char* dsttile = dsttilerow;
795 for (int j = 0; j < ntilesu; j++) {
796 PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
797 if (!t) { i = ntilesv; break; }
798 if (t->isConstant())
799 PtexUtils::fill(t->getData(), dsttile, stride,
800 tileures, tilevres, _pixelsize);
801 else
802 PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
803 tilevres, tilerowlen);
804 dsttile += tilerowlen;
805 }
806 dsttilerow += stride * tilevres;
807 }
808 }
809 else {
810 PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
811 }
812 }
813
814
815 PtexFaceData* PtexReader::getData(int faceid)
816 {
817 if (faceid < 0 || size_t(faceid) >= _header.nfaces) return 0;
818 if (!_ok) return 0;
819
820 FaceInfo& fi = _faceinfo[faceid];
821 if (fi.isConstant() || fi.res == 0) {
822 return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
823 }
824
825 // get level zero (full) res face
826 AutoLockCache locker(_cache->cachelock);
827 Level* level = getLevel(0);
828 FaceData* face = getFace(0, level, faceid);
829 level->unref();
830 return face;
831 }
832
833
834 PtexFaceData* PtexReader::getData(int faceid, Res res)
835 {
836 if (!_ok) return 0;
837 if (faceid < 0 || size_t(faceid) >= _header.nfaces) return 0;
838
839 FaceInfo& fi = _faceinfo[faceid];
840 if ((fi.isConstant() && res >= 0) || res == 0) {
841 return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
842 }
843
844 // lock cache (can't autolock since we might need to unlock early)
845 _cache->cachelock.lock();
846
847
848 // determine how many reduction levels are needed
849 int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
850
851 if (redu == 0 && redv == 0) {
852 // no reduction - get level zero (full) res face
853 Level* level = getLevel(0);
854 FaceData* face = getFace(0, level, faceid);
855 level->unref();
856 _cache->cachelock.unlock();
857 return face;
858 }
859
860 if (redu == redv && !fi.hasEdits() && res >= 0) {
861 // reduction is symmetric and non-negative
862 // and face has no edits => access data from reduction level (if present)
863 int levelid = redu;
864 if (size_t(levelid) < _levels.size()) {
865 Level* level = getLevel(levelid);
866
867 // get reduction face id
868 int rfaceid = _rfaceids[faceid];
869
870 // get the face data (if present)
871 FaceData* face = 0;
872 if (size_t(rfaceid) < level->faces.size())
873 face = getFace(levelid, level, rfaceid);
874 level->unref();
875 if (face) {
876 _cache->cachelock.unlock();
877 return face;
878 }
879 }
880 }
881
882 // dynamic reduction required - look in dynamic reduction cache
883 FaceData*& face = _reductions[ReductionKey(faceid, res)];
884 if (face) {
885 face->ref();
886 _cache->cachelock.unlock();
887 return face;
888 }
889
890 // not found, generate new reduction
891 // unlock cache - getData and reduce will handle their own locking
892 _cache->cachelock.unlock();
893
894 if (res.ulog2 < 0 || res.vlog2 < 0) {
895 std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
896 return 0;
897 }
898 if (redu < 0 || redv < 0) {
899 std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
900 return 0;
901 }
902 if (_header.meshtype == mt_triangle)
903 {
904 if (redu != redv) {
905 std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
906 return 0;
907 }
908 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
909 FaceData* src = static_cast<FaceData*>(psrc.get());
910 assert(src);
911 if (src) src->reduce(face, this, res, PtexUtils::reduceTri);
912 return face;
913 }
914
915 // determine which direction to blend
916 bool blendu;
917 if (redu == redv) {
918 // for symmetric face blends, alternate u and v blending
919 blendu = (res.ulog2 & 1);
920 }
921 else blendu = redu > redv;
922
923 if (blendu) {
924 // get next-higher u-res and reduce in u
925 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
926 FaceData* src = static_cast<FaceData*>(psrc.get());
927 assert(src);
928 if (src) src->reduce(face, this, res, PtexUtils::reduceu);
929 }
930 else {
931 // get next-higher v-res and reduce in v
932 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
933 FaceData* src = static_cast<FaceData*>(psrc.get());
934 assert(src);
935 if (src) src->reduce(face, this, res, PtexUtils::reducev);
936 }
937
938 return face;
939 }
940
941
942 void PtexReader::blendFaces(FaceData*& face, int faceid, Res res, bool blendu)
943 {
944 Res pres; // parent res, 1 higher in blend direction
945 int length; // length of blend edge (1xN or Nx1)
946 int e1, e2; // neighboring edge ids
947 if (blendu) {
948 assert(res.ulog2 < 0); // res >= 0 requires reduction, not blending
949 length = (res.vlog2 <= 0 ? 1 : res.v());
950 e1 = e_bottom; e2 = e_top;
951 pres = Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2);
952 }
953 else {
954 assert(res.vlog2 < 0);
955 length = (res.ulog2 <= 0 ? 1 : res.u());
956 e1 = e_right; e2 = e_left;
957 pres = Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1));
958 }
959
960 // get neighbor face ids
961 FaceInfo& f = _faceinfo[faceid];
962 int nf1 = f.adjfaces[e1], nf2 = f.adjfaces[e2];
963
964 // compute rotation of faces relative to current
965 int r1 = (f.adjedge(e1)-e1+2)&3;
966 int r2 = (f.adjedge(e2)-e2+2)&3;
967
968 // swap u and v res for faces rotated +/- 90 degrees
969 Res pres1 = pres, pres2 = pres;
970 if (r1 & 1) pres1.swapuv();
971 if (r2 & 1) pres2.swapuv();
972
973 // ignore faces that have insufficient res (unlikely, but possible)
974 if (nf1 >= 0 && !(_faceinfo[nf1].res >= pres)) nf1 = -1;
975 if (nf2 >= 0 && !(_faceinfo[nf2].res >= pres)) nf2 = -1;
976
977 // get parent face data
978 int nf = 1; // number of faces to blend (1 to 3)
979 bool flip[3]; // true if long dimension needs to be flipped
980 PtexFaceData* psrc[3]; // the face data
981 psrc[0] = getData(faceid, pres);
982 flip[0] = 0; // don't flip main face
983 if (nf1 >= 0) {
984 // face must be flipped if rot is 1 or 2 for blendu, or 2 or 3 for blendv
985 // thus, just add the blendu bool val to align the ranges and check bit 1
986 // also, no need to flip if length is zero
987 flip[nf] = length ? (r1 + blendu) & 1 : 0;
988 psrc[nf++] = getData(nf1, pres1);
989 }
990 if (nf2 >= 0) {
991 flip[nf] = length ? (r2 + blendu) & 1 : 0;
992 psrc[nf++] = getData(nf2, pres2);
993 }
994
995 // get reduce lock and make sure we still need to reduce
996 AutoMutex rlocker(reducelock);
997 if (face) {
998 // another thread must have generated it while we were waiting
999 AutoLockCache locker(_cache->cachelock);
1000 // make sure it's still there now that we have the lock
1001 if (face) {
1002 face->ref();
1003 // release parent data
1004 for (int i = 0; i < nf; i++) psrc[i]->release();
1005 return;
1006 }
1007 }
1008
1009 // allocate a new face data (1 x N or N x 1)
1010 DataType dt = datatype();
1011 int nchan = nchannels();
1012 int size = _pixelsize * length;
1013 PackedFace* pf = new PackedFace((void**)&face, _cache, res,
1014 _pixelsize, size);
1015 void* data = pf->getData();
1016 if (nf == 1) {
1017 // no neighbors - just copy face
1018 memcpy(data, psrc[0]->getData(), size);
1019 }
1020 else {
1021 float weight = 1.0f / (float)nf;
1022 memset(data, 0, size);
1023 for (int i = 0; i < nf; i++)
1024 PtexUtils::blend(psrc[i]->getData(), weight, data, flip[i],
1025 length, dt, nchan);
1026 }
1027
1028 {
1029 AutoLockCache clocker(_cache->cachelock);
1030 face = pf;
1031
1032 // clean up unused data
1033 _cache->purgeData();
1034 }
1035
1036 // release parent data
1037 for (int i = 0; i < nf; i++) psrc[i]->release();
1038 }
1039
1040
1041 void PtexReader::getPixel(int faceid, int u, int v,
1042 float* result, int firstchan, int nchannels)
1043 {
1044 memset(result, 0, sizeof(*result)*nchannels);
1045
1046 // clip nchannels against actual number available
1047 nchannels = PtexUtils::min(nchannels,
1048 _header.nchannels-firstchan);
1049 if (nchannels <= 0) return;
1050
1051 // get raw pixel data
1052 PtexPtr<PtexFaceData> data ( getData(faceid) );
1053 if (!data) return;
1054 void* pixel = alloca(_pixelsize);
1055 data->getPixel(u, v, pixel);
1056
1057 // adjust for firstchan offset
1058 int datasize = DataSize(_header.datatype);
1059 if (firstchan)
1060 pixel = (char*) pixel + datasize * firstchan;
1061
1062 // convert/copy to result as needed
1063 if (_header.datatype == dt_float)
1064 memcpy(result, pixel, datasize * nchannels);
1065 else
1066 ConvertToFloat(result, pixel, _header.datatype, nchannels);
1067 }
1068
1069
1070 void PtexReader::getPixel(int faceid, int u, int v,
1071 float* result, int firstchan, int nchannels,
1072 Ptex::Res res)
1073 {
1074 memset(result, 0, nchannels);
1075
1076 // clip nchannels against actual number available
1077 nchannels = PtexUtils::min(nchannels,
1078 _header.nchannels-firstchan);
1079 if (nchannels <= 0) return;
1080
1081 // get raw pixel data
1082 PtexPtr<PtexFaceData> data ( getData(faceid, res) );
1083 if (!data) return;
1084 void* pixel = alloca(_pixelsize);
1085 data->getPixel(u, v, pixel);
1086
1087 // adjust for firstchan offset
1088 int datasize = DataSize(_header.datatype);
1089 if (firstchan)
1090 pixel = (char*) pixel + datasize * firstchan;
1091
1092 // convert/copy to result as needed
1093 if (_header.datatype == dt_float)
1094 memcpy(result, pixel, datasize * nchannels);
1095 else
1096 ConvertToFloat(result, pixel, _header.datatype, nchannels);
1097 }
1098
1099
1100 void PtexReader::PackedFace::reduce(FaceData*& face, PtexReader* r,
1101 Res newres, PtexUtils::ReduceFn reducefn)
1102 {
1103 // get reduce lock and make sure we still need to reduce
1104 AutoMutex rlocker(r->reducelock);
1105 if (face) {
1106 // another thread must have generated it while we were waiting
1107 AutoLockCache clocker(_cache->cachelock);
1108 // make sure it's still there now that we have the lock
1109 if (face) {
1110 face->ref();
1111 return;
1112 }
1113 }
1114
1115 // allocate a new face and reduce image
1116 DataType dt = r->datatype();
1117 int nchan = r->nchannels();
1118 PackedFace* pf = new PackedFace((void**)&face, _cache, newres,
1119 _pixelsize, _pixelsize * newres.size());
1120 // reduce and copy into new face
1121 reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
1122 pf->_data, _pixelsize * newres.u(), dt, nchan);
1123 AutoLockCache clocker(_cache->cachelock);
1124 face = pf;
1125
1126 // clean up unused data
1127 _cache->purgeData();
1128 }
1129
1130
1131
1132 void PtexReader::ConstantFace::reduce(FaceData*& face, PtexReader*,
1133 Res, PtexUtils::ReduceFn)
1134 {
1135 // get cache lock (just to protect the ref count)
1136 AutoLockCache locker(_cache->cachelock);
1137
1138 // must make a new constant face (even though it's identical to this one)
1139 // because it will be owned by a different reduction level
1140 // and will therefore have a different parent
1141 ConstantFace* pf = new ConstantFace((void**)&face, _cache, _pixelsize);
1142 memcpy(pf->_data, _data, _pixelsize);
1143 face = pf;
1144 }
1145
1146
1147 void PtexReader::TiledFaceBase::reduce(FaceData*& face, PtexReader* r,
1148 Res newres, PtexUtils::ReduceFn reducefn)
1149 {
1150 // get reduce lock and make sure we still need to reduce
1151 AutoMutex rlocker(r->reducelock);
1152 if (face) {
1153 // another thread must have generated it while we were waiting
1154 AutoLockCache clocker(_cache->cachelock);
1155 // make sure it's still there now that we have the lock
1156 if (face) {
1157 face->ref();
1158 return;
1159 }
1160 }
1161
1162 /* Tiled reductions should generally only be anisotropic (just u
1163 or v, not both) since isotropic reductions are precomputed and
1164 stored on disk. (This function should still work for isotropic
1165 reductions though.)
1166
1167 In the anisotropic case, the number of tiles should be kept the
1168 same along the direction not being reduced in order to preserve
1169 the laziness of the file access. In contrast, if reductions
1170 were not tiled, then any reduction would read all the tiles and
1171 defeat the purpose of tiling.
1172 */
1173
1174 // keep new face local until fully initialized
1175 FaceData* volatile newface = 0;
1176
1177 // don't tile if either dimension is 1 (rare, would complicate blendFaces too much)
1178 // also, don't tile triangle reductions (too complicated)
1179 Res newtileres;
1180 bool isTriangle = r->_header.meshtype == mt_triangle;
1181 if (newres.ulog2 == 1 || newres.vlog2 == 1 || isTriangle) {
1182 newtileres = newres;
1183 }
1184 else {
1185 // propagate the tile res to the reduction
1186 newtileres = _tileres;
1187 // but make sure tile isn't larger than the new face!
1188 if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1189 if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1190 }
1191
1192
1193 // determine how many tiles we will have on the reduction
1194 int newntiles = newres.ntiles(newtileres);
1195
1196 if (newntiles == 1) {
1197 // no need to keep tiling, reduce tiles into a single face
1198 // first, get all tiles and check if they are constant (with the same value)
1199 PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1200 bool allConstant = true;
1201 for (int i = 0; i < _ntiles; i++) {
1202 PtexFaceData* tile = tiles[i] = getTile(i);
1203 allConstant = (allConstant && tile->isConstant() &&
1204 (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1205 _pixelsize))));
1206 }
1207 if (allConstant) {
1208 // allocate a new constant face
1209 newface = new ConstantFace((void**)&face, _cache, _pixelsize);
1210 memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1211 }
1212 else if (isTriangle) {
1213 // reassemble all tiles into temporary contiguous image
1214 // (triangle reduction doesn't work on tiles)
1215 int tileures = _tileres.u();
1216 int tilevres = _tileres.v();
1217 int sstride = _pixelsize * tileures;
1218 int dstride = sstride * _ntilesu;
1219 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1220
1221 char* tmp = (char*) malloc(_ntiles * _tileres.size() * _pixelsize);
1222 char* tmpptr = tmp;
1223 for (int i = 0; i < _ntiles;) {
1224 PtexFaceData* tile = tiles[i];
1225 if (tile->isConstant())
1226 PtexUtils::fill(tile->getData(), tmpptr, dstride,
1227 tileures, tilevres, _pixelsize);
1228 else
1229 PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1230 i++;
1231 tmpptr += i%_ntilesu ? sstride : dstepv;
1232 }
1233
1234 // allocate a new packed face
1235 newface = new PackedFace((void**)&face, _cache, newres,
1236 _pixelsize, _pixelsize * newres.size());
1237 // reduce and copy into new face
1238 reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1239 newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1240
1241 free(tmp);
1242 }
1243 else {
1244 // allocate a new packed face
1245 newface = new PackedFace((void**)&face, _cache, newres,
1246 _pixelsize, _pixelsize*newres.size());
1247
1248 int tileures = _tileres.u();
1249 int tilevres = _tileres.v();
1250 int sstride = _pixelsize * tileures;
1251 int dstride = _pixelsize * newres.u();
1252 int dstepu = dstride/_ntilesu;
1253 int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1254
1255 char* dst = (char*) newface->getData();
1256 for (int i = 0; i < _ntiles;) {
1257 PtexFaceData* tile = tiles[i];
1258 if (tile->isConstant())
1259 PtexUtils::fill(tile->getData(), dst, dstride,
1260 newres.u()/_ntilesu, newres.v()/_ntilesv,
1261 _pixelsize);
1262 else
1263 reducefn(tile->getData(), sstride, tileures, tilevres,
1264 dst, dstride, _dt, _nchan);
1265 i++;
1266 dst += i%_ntilesu ? dstepu : dstepv;
1267 }
1268 }
1269 // release the tiles
1270 for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1271 }
1272 else {
1273 // otherwise, tile the reduced face
1274 newface = new TiledReducedFace((void**)&face, _cache, newres, newtileres,
1275 _dt, _nchan, this, reducefn);
1276 }
1277 AutoLockCache clocker(_cache->cachelock);
1278 face = newface;
1279
1280 // clean up unused data
1281 _cache->purgeData();
1282 }
1283
1284
1285 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1286 {
1287 int tileu = ui >> _tileres.ulog2;
1288 int tilev = vi >> _tileres.vlog2;
1289 PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1290 tile->getPixel(ui - (tileu<<_tileres.ulog2),
1291 vi - (tilev<<_tileres.vlog2), result);
1292 }
1293
1294
1295
1296 PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
1297 {
1298 _cache->cachelock.lock();
1299 FaceData*& face = _tiles[tile];
1300 if (face) {
1301 face->ref();
1302 _cache->cachelock.unlock();
1303 return face;
1304 }
1305
1306 // first, get all parent tiles for this tile
1307 // and check if they are constant (with the same value)
1308 int pntilesu = _parentface->ntilesu();
1309 int pntilesv = _parentface->ntilesv();
1310 int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1311 int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1312
1313 int ntiles = nu*nv; // num parent tiles for this tile
1314 PtexFaceData** tiles = (PtexFaceData**) alloca(ntiles * sizeof(PtexFaceData*));
1315 bool allConstant = true;
1316 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1317 for (int i = 0; i < ntiles;) {
1318 // temporarily release cache lock while we get parent tile
1319 _cache->cachelock.unlock();
1320 PtexFaceData* tile = tiles[i] = _parentface->getTile(ptile);
1321 _cache->cachelock.lock();
1322 allConstant = (allConstant && tile->isConstant() &&
1323 (i==0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1324 _pixelsize))));
1325 i++;
1326 ptile += i%nu? 1 : pntilesu - nu + 1;
1327 }
1328
1329 // make sure another thread didn't make the tile while we were checking
1330 if (face) {
1331 face->ref();
1332 _cache->cachelock.unlock();
1333 // release the tiles
1334 for (int i = 0; i < ntiles; i++) tiles[i]->release();
1335 return face;
1336 }
1337
1338 if (allConstant) {
1339 // allocate a new constant face
1340 face = new ConstantFace((void**)&face, _cache, _pixelsize);
1341 memcpy(face->getData(), tiles[0]->getData(), _pixelsize);
1342 }
1343 else {
1344 // allocate a new packed face for the tile
1345 face = new PackedFace((void**)&face, _cache, _tileres,
1346 _pixelsize, _pixelsize*_tileres.size());
1347
1348 // generate reduction from parent tiles
1349 int ptileures = _parentface->tileres().u();
1350 int ptilevres = _parentface->tileres().v();
1351 int sstride = ptileures * _pixelsize;
1352 int dstride = _tileres.u() * _pixelsize;
1353 int dstepu = dstride/nu;
1354 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1355
1356 char* dst = (char*) face->getData();
1357 for (int i = 0; i < ntiles;) {
1358 PtexFaceData* tile = tiles[i];
1359 if (tile->isConstant())
1360 PtexUtils::fill(tile->getData(), dst, dstride,
1361 _tileres.u()/nu, _tileres.v()/nv,
1362 _pixelsize);
1363 else
1364 _reducefn(tile->getData(), sstride, ptileures, ptilevres,
1365 dst, dstride, _dt, _nchan);
1366 i++;
1367 dst += i%nu ? dstepu : dstepv;
1368 }
1369 }
1370
1371 _cache->cachelock.unlock();
1372
1373 // release the tiles
1374 for (int i = 0; i < ntiles; i++) tiles[i]->release();
1375 return face;
1376 }
PtexCacheImpl::handlePendingDelete
void handlePendingDelete()
Definition: PtexCache.h:220
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid)
Definition: PtexReader.h:497
Ptex::e_left
Left edge, from UV (0,1) to (0,0)
Definition: Ptexture.h:103
PtexReader::_ownsCache
bool _ownsCache
Definition: PtexReader.h:574
PtexReader::_extheader
ExtHeader _extheader
Definition: PtexReader.h:581
PtexIO::Header::meshtype
MeshType meshtype
Definition: PtexIO.h:45
PtexReader::FaceData::reduce
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)=0
PtexIO::ExtHeader::editdatapos
uint64_t editdatapos
Definition: PtexIO.h:69
PtexReader::setOwnsCache
void setOwnsCache()
Definition: PtexReader.h:78
PtexIO::EditFaceDataHeader::faceinfo
FaceInfo faceinfo
Definition: PtexIO.h:91
PtexIO::Header::nfaces
uint32_t nfaces
Definition: PtexIO.h:50
Ptex::Res::ntiles
int ntiles(Res tileres) const
Determine the total number of tiles for the given tile res.
Definition: Ptexture.h:220
Ptex::Res::ntilesv
int ntilesv(Res tileres) const
Determine the number of tiles in the v direction for the given tile res.
Definition: Ptexture.h:217
PtexIO::Header::levelinfosize
uint32_t levelinfosize
Definition: PtexIO.h:54
PtexReader::_error
std::string _error
Definition: PtexReader.h:576
PtexReader::_levelinfo
safevector< LevelInfo > _levelinfo
Definition: PtexReader.h:598
PtexUtils::multalpha
static void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:562
PtexIO::FaceDataHeader
Definition: PtexIO.h:78
PtexReader::MetaData::_lmdRefs
std::vector< LargeMetaData * > _lmdRefs
Definition: PtexReader.h:266
PtexReader::reducelock
Mutex reducelock
Definition: PtexReader.h:466
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexReader.cpp:170
PtexReader::PtexReader
PtexReader(void **parent, PtexCacheImpl *cache, bool premultiply, PtexInputHandler *handler)
Definition: PtexReader.cpp:126
PtexReader::_io
PtexInputHandler * _io
Definition: PtexReader.h:572
Ptex::FaceInfo::isConstant
bool isConstant() const
Determine if face is constant (by checking a flag).
Definition: Ptexture.h:270
PtexIO::Header::nlevels
uint16_t nlevels
Definition: PtexIO.h:49
PtexReader::readFaceInfo
void readFaceInfo()
Definition: PtexReader.cpp:195
Ptex::DataSize
static int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:132
Ptex::String
Memory-managed string.
Definition: Ptexture.h:303
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition: PtexReader.cpp:185
PtexCacheImpl::purgeData
void purgeData()
Definition: PtexCache.h:240
PtexReader::readLevelInfo
void readLevelInfo()
Definition: PtexReader.cpp:220
PtexReader::MetaData::getEntry
Entry * getEntry(const char *key)
Definition: PtexReader.cpp:265
Ptex::e_top
Top edge, from UV (1,1) to (0,1)
Definition: Ptexture.h:102
PtexIO::ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition: PtexIO.h:65
PtexUtils::reduceTri
static void reduceTri(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:389
PtexIO::AllocaMax
static const int AllocaMax
Definition: PtexIO.h:111
PtexReader::_levelpos
safevector< FilePos > _levelpos
Definition: PtexReader.h:599
PtexReader::TiledFace::_offsets
safevector< FilePos > _offsets
Definition: PtexReader.h:419
PtexIO::Header::nchannels
uint16_t nchannels
Definition: PtexIO.h:48
PtexCache::get
virtual PtexTexture * get(const char *path, Ptex::String &error)=0
Open a texture.
Ptex::DataType
DataType
Type of data stored in texture file.
Definition: Ptexture.h:83
PtexReader::_metaedits
safevector< MetaEdit > _metaedits
Definition: PtexReader.h:608
PtexUtils::blend
static void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchannels)
Definition: PtexUtils.cpp:463
PtexCachedData::ref
void ref()
Definition: PtexCache.h:288
PtexReader::TiledFace
Definition: PtexReader.h:391
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition: PtexReader.h:585
PtexIO::EditMetaDataHeader::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:96
PtexReader::_levels
safevector< Level * > _levels
Definition: PtexReader.h:600
PtexMetaData
Meta data accessor.
Definition: Ptexture.h:337
PtexIO::HeaderSize
static const int HeaderSize
Definition: PtexIO.h:100
Ptex::FaceInfo::flags
uint8_t flags
Flags.
Definition: Ptexture.h:240
PtexReader::PackedFace::data
void * data()
Definition: PtexReader.h:307
PtexReader::MetaData
Definition: PtexReader.h:110
PtexUtils::min
static T min(T a, T b)
Definition: PtexUtils.h:116
Ptex::mt_triangle
Mesh is triangle-based.
Definition: Ptexture.h:78
PtexReader::_metadata
MetaData * _metadata
Definition: PtexReader.h:592
PtexCachedFile::unref
void unref()
Definition: PtexCache.h:272
PtexIO::Header::constdatasize
uint32_t constdatasize
Definition: PtexIO.h:53
PtexIO::Header::pixelSize
int pixelSize() const
Definition: PtexIO.h:59
PtexCache
File-handle and memory cache for reading ptex files.
Definition: Ptexture.h:634
PtexReader::readConstData
void readConstData()
Definition: PtexReader.cpp:240
PtexReader::readBlock
bool readBlock(void *data, int size, bool reportError=true)
Definition: PtexReader.cpp:503
PtexReader::_ok
bool _ok
Definition: PtexReader.h:575
PtexReader::path
virtual const char * path()
Path that file was opened with.
Definition: PtexReader.h:80
PtexReader::_path
std::string _path
Definition: PtexReader.h:579
PtexIO::Header::faceinfosize
uint32_t faceinfosize
Definition: PtexIO.h:52
PtexReader::_constdata
uint8_t * _constdata
Definition: PtexReader.h:591
PtexUtils::copy
static void copy(const void *src, int sstride, void *dst, int dstride, int nrows, int rowlen)
Definition: PtexUtils.cpp:421
PtexIO::LevelInfoSize
static const int LevelInfoSize
Definition: PtexIO.h:102
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition: PtexReader.cpp:545
PtexReader::FaceData
Definition: PtexReader.h:290
PtexReader::MetaEdit::zipsize
int zipsize
Definition: PtexReader.h:605
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition: PtexReader.cpp:255
PtexIO::et_editfacedata
Definition: PtexIO.h:88
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexCache::create
static PtexCache * create(int maxFiles=0, int maxMem=0, bool premultiply=false, PtexInputHandler *handler=0)
Create a cache with the specified limits.
Definition: PtexCache.cpp:410
PtexCacheImpl::setPendingDelete
void setPendingDelete()
Definition: PtexCache.h:219
PtexIO::EditMetaDataHeaderSize
static const int EditMetaDataHeaderSize
Definition: PtexIO.h:105
Ptex::Res::v
int v() const
V resolution in texels.
Definition: Ptexture.h:181
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexIO::Header::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:57
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition: PtexReader.h:224
PtexIO::EditFaceDataHeader
Definition: PtexIO.h:89
STATS_INC
#define STATS_INC(x)
Definition: PtexCache.h:97
Ptex::e_bottom
Bottom edge, from UV (0,0) to (1,0)
Definition: Ptexture.h:100
PtexCachedFile::_cache
PtexCacheImpl * _cache
Definition: PtexCache.h:275
PtexReader::PackedFace::_data
void * _data
Definition: PtexReader.h:324
PtexReader::_reductions
ReductionMap _reductions
Definition: PtexReader.h:636
PtexCachedData::unref
void unref()
Definition: PtexCache.h:289
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexIO::enc_constant
Definition: PtexIO.h:77
FilePos
off_t FilePos
Definition: PtexPlatform.h:85
Ptex::FaceInfo::adjfaces
int32_t adjfaces[4]
Adjacent faces (-1 == no adjacent face).
Definition: Ptexture.h:241
PtexIO::LevelInfo::levelheadersize
uint32_t levelheadersize
Definition: PtexIO.h:73
PtexIO::EditMetaDataHeader::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:95
PtexIO::ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition: PtexIO.h:66
PtexReader::_faceedits
safevector< FaceEdit > _faceedits
Definition: PtexReader.h:616
PtexIO::FaceDataHeader::blocksize
uint32_t blocksize() const
Definition: PtexIO.h:80
PtexReader::_rfaceids
safevector< uint32_t > _rfaceids
Definition: PtexReader.h:596
PtexIO::ExtHeaderSize
static const int ExtHeaderSize
Definition: PtexIO.h:101
PtexReader::blendFaces
void blendFaces(FaceData *&face, int faceid, Res res, bool blendu)
Definition: PtexReader.cpp:942
PtexReader::_zstream
z_stream_s _zstream
Definition: PtexReader.h:638
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:388
Ptex::Res::u
int u() const
U resolution in texels.
Definition: Ptexture.h:178
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition: PtexReader.h:221
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize)
Definition: PtexReader.cpp:371
PtexReader::getRes
Res getRes(int levelid, int faceid)
Definition: PtexReader.h:505
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
Ptex::Res::vlog2
int8_t vlog2
log base 2 of v resolution, in texels
Definition: Ptexture.h:163
PtexReader::ConstantFace::reduce
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
Definition: PtexReader.cpp:1132
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition: PtexReader.h:587
PtexUtils::genRfaceids
static void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:613
Ptex::Res::ntilesu
int ntilesu(Res tileres) const
Determine the number of tiles in the u direction for the given tile res.
Definition: Ptexture.h:214
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition: PtexReader.h:225
PtexReader::FaceEdit::faceid
int faceid
Definition: PtexReader.h:613
PtexIO::Header::version
uint32_t version
Definition: PtexIO.h:44
PtexReader::TiledFaceBase::reduce
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
Definition: PtexReader.cpp:1147
Ptex::dt_float
Single-precision (32-bit) floating point.
Definition: Ptexture.h:87
PtexIO::LevelInfo::nfaces
uint32_t nfaces
Definition: PtexIO.h:74
PtexReader::Level::offsets
safevector< FilePos > offsets
Definition: PtexReader.h:450
PtexInternal::_SpinLock::unlock
void unlock()
Definition: PtexPlatform.h:146
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition: PtexReader.cpp:673
PtexIO::Header::hasAlpha
bool hasAlpha() const
Definition: PtexIO.h:60
PtexReader::readMetaData
void readMetaData()
Definition: PtexReader.cpp:320
PtexIO::Header::datatype
DataType datatype
Definition: PtexIO.h:46
PtexReader::MetaData::LargeMetaData
Definition: PtexReader.h:207
PtexReader::~PtexReader
virtual ~PtexReader()
Definition: PtexReader.cpp:146
PtexReader::MetaEdit::pos
FilePos pos
Definition: PtexReader.h:604
PtexHashMap::end
iterator end() const
Returns an iteraot referencing the location just beyond the table.
Definition: PtexHashMap.h:149
PtexReader::computeOffsets
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition: PtexReader.h:538
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.h:132
Ptex::FaceInfo::hasEdits
bool hasEdits() const
Determine if face has edits in the file (by checking a flag).
Definition: Ptexture.h:276
PtexReader
Definition: PtexReader.h:72
PtexReader::readlock
Mutex readlock
Definition: PtexReader.h:465
PtexReader::Level::fdh
safevector< FaceDataHeader > fdh
Definition: PtexReader.h:449
PtexReader::MetaData::Entry
Definition: PtexReader.h:218
PtexCache::purgeAll
virtual void purgeAll()=0
Remove all texture files from the cache.
PtexIO::enc_zipped
Definition: PtexIO.h:77
PtexPtr::get
T * get()
Get pointer value.
Definition: Ptexture.h:971
PtexReader::_hasEdits
bool _hasEdits
Definition: PtexReader.h:593
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition: PtexReader.h:582
PtexReader::setError
void setError(const char *error)
Definition: PtexReader.h:470
PtexIO::FaceDataHeader::encoding
Encoding encoding() const
Definition: PtexIO.h:81
PtexInternal::_SpinLock::lock
void lock()
Definition: PtexPlatform.h:145
PtexReader::FaceEdit
Definition: PtexReader.h:610
PtexReader::_editdatapos
FilePos _editdatapos
Definition: PtexReader.h:589
PtexLruItem::orphanList
static void orphanList(T &list)
Definition: PtexCache.h:116
PtexCachedData::_cache
PtexCacheImpl * _cache
Definition: PtexCache.h:293
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexHashMap< ReductionKey, FaceData *, ReductionKey::Hasher >::iterator
friend class iterator
Definition: PtexHashMap.h:194
PtexReader::_res_r
safevector< Res > _res_r
Definition: PtexReader.h:597
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition: PtexReader.cpp:518
Ptex::FaceInfo::flag_hasedits
Definition: Ptexture.h:290
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition: PtexReader.h:584
PtexReader::datatype
DataType datatype() const
Definition: PtexReader.h:103
PtexIO::Magic
static const uint32_t Magic
Definition: PtexIO.h:99
PtexIO::Header::magic
uint32_t magic
Definition: PtexIO.h:43
PtexIO::Header::alphachan
int32_t alphachan
Definition: PtexIO.h:47
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition: PtexReader.cpp:759
PtexReader::_premultiply
bool _premultiply
Definition: PtexReader.h:573
PtexUtils::fill
static void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:405
Ptex::FaceInfo::adjedge
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
Definition: Ptexture.h:264
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition: PtexReader.cpp:1285
PtexReader::Level
Definition: PtexReader.h:447
PtexReader::_constdatapos
FilePos _constdatapos
Definition: PtexReader.h:583
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize)
Definition: PtexReader.cpp:397
PtexReader::getLevel
Level * getLevel(int levelid)
Definition: PtexReader.h:488
PtexIO::EditFaceDataHeader::faceid
uint32_t faceid
Definition: PtexIO.h:90
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition: PtexReader.h:577
PtexReader::ConstantFace
Definition: PtexReader.h:327
Ptex::Res::size
int size() const
Total size of specified texture in texels (u * v).
Definition: Ptexture.h:190
PtexReader::getPixel
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
Definition: PtexReader.cpp:1041
PtexReader::PackedFace
Definition: PtexReader.h:302
PtexReader::nchannels
int nchannels() const
Definition: PtexReader.h:104
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition: PtexReader.cpp:46
Ptex::Res::swapuv
void swapuv()
Swap the u and v resolution values in place.
Definition: Ptexture.h:205
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid)
Definition: PtexReader.cpp:590
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:955
PtexFaceData::isTiled
virtual bool isTiled()=0
True if this data block is tiled.
PtexReader::_metadatapos
FilePos _metadatapos
Definition: PtexReader.h:586
PtexIO::ExtHeader::lmddatasize
uint64_t lmddatasize
Definition: PtexIO.h:67
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition: PtexReader.cpp:700
PtexReader::PackedFace::getData
virtual void * getData()
Access the data from this data block.
Definition: PtexReader.h:313
PtexReader::_header
Header _header
Definition: PtexReader.h:580
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexIO::Header::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:58
PtexIO::ExtHeader::editdatasize
uint64_t editdatasize
Definition: PtexIO.h:68
PtexReader::_pixelsize
int _pixelsize
Definition: PtexReader.h:590
Ptex::Res::ulog2
int8_t ulog2
log base 2 of u resolution, in texels
Definition: Ptexture.h:162
PtexFaceData::getPixel
virtual void getPixel(int u, int v, void *result)=0
Read a single texel from the data block.
PtexIO::Header::extheadersize
uint32_t extheadersize
Definition: PtexIO.h:51
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition: PtexReader.cpp:1296
PtexReader::FaceEdit::fdh
FaceDataHeader fdh
Definition: PtexReader.h:614
Ptex::e_right
Right edge, from UV (1,0) to (1,1)
Definition: Ptexture.h:101
PtexTexture
Interface for reading data from a ptex file.
Definition: Ptexture.h:439
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition: PtexReader.h:223
PtexReader::getConstData
uint8_t * getConstData()
Definition: PtexReader.h:496
PtexIO::BlockSize
static const int BlockSize
Definition: PtexIO.h:109
PtexReader::Level::faces
safevector< FaceData * > faces
Definition: PtexReader.h:451
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:161
PtexReader::PackedFace::reduce
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
Definition: PtexReader.cpp:1100
PtexReader::TiledFace::_fdh
safevector< FaceDataHeader > _fdh
Definition: PtexReader.h:418
PtexCachedFile
Cache entry for open file handle.
Definition: PtexCache.h:265
PtexReader::_faceinfo
safevector< FaceInfo > _faceinfo
Definition: PtexReader.h:595
PtexReader::TiledReducedFace
Definition: PtexReader.h:423
PtexCacheImpl::cachelock
CacheLock cachelock
Definition: PtexCache.h:216
PtexUtils::reduceu
static void reduceu(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:316
PtexUtils::interleave
static void interleave(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:171
PtexIO::FaceDataHeaderSize
static const int FaceDataHeaderSize
Definition: PtexIO.h:103
PtexReader::MetaData::_map
MetaMap _map
Definition: PtexReader.h:264
PtexReader::FaceEdit::pos
FilePos pos
Definition: PtexReader.h:612
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition: PtexReader.cpp:63
PtexCacheImpl
Ptex cache implementation.
Definition: PtexCache.h:192
PtexIO::enc_tiled
Definition: PtexIO.h:77
PtexReader::ConstDataPtr
Definition: PtexReader.h:270
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition: PtexReader.h:385
PtexUtils::reducev
static void reducev(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.cpp:349
Ptex::FaceInfo::res
Res res
Resolution of face.
Definition: Ptexture.h:238
PtexLruItem::orphan
void orphan()
Definition: PtexCache.h:107
PtexReader::MetaEdit::memsize
int memsize
Definition: PtexReader.h:606
PtexInternal::AutoLock
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:58
PtexIO::EditMetaDataHeader
Definition: PtexIO.h:94
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:237
PtexIO::Header::leveldatasize
uint64_t leveldatasize
Definition: PtexIO.h:56
PtexHashMap::begin
iterator begin() const
Returns an iterator referencing the beginning of the table.
Definition: PtexHashMap.h:136
PtexIO::enc_diffzipped
Definition: PtexIO.h:77
PtexReader::ReductionKey
Definition: PtexReader.h:618
STATS_ADD
#define STATS_ADD(x, y)
Definition: PtexCache.h:98
PtexUtils::decodeDifference
static void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:253
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, void *data)
Definition: PtexReader.h:188
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition: PtexReader.h:212
PtexReader::readEditFaceData
void readEditFaceData()
Definition: PtexReader.cpp:457
PtexReader::MetaData::addLmdEntry
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize)
Definition: PtexReader.h:196
PtexReader::readEditData
void readEditData()
Definition: PtexReader.cpp:425
PtexIO::LevelInfo
Definition: PtexIO.h:71
Ptex::ConvertToFloat
static void ConvertToFloat(float *dst, const void *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from the given data type to float.
Definition: PtexUtils.cpp:107
PtexReader::seek
void seek(FilePos pos)
Definition: PtexReader.h:477
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition: PtexReader.h:226
PtexUtils.h
PtexIO::LittleEndian
static bool LittleEndian()
Definition: PtexIO.h:114
PtexIO::EditFaceDataHeaderSize
static const int EditFaceDataHeaderSize
Definition: PtexIO.h:104
PtexReader.h
Ptex::String::c_str
const char * c_str() const
Definition: Ptexture.h:312
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexReader::readEditMetaData
void readEditMetaData()
Definition: PtexReader.cpp:488
PtexReader::tell
FilePos tell()
Definition: PtexReader.h:476
PtexIO::et_editmetadata
Definition: PtexIO.h:88
PtexIO::EditFaceDataHeader::fdh
FaceDataHeader fdh
Definition: PtexIO.h:92
PtexReader::MetaData::Entry::data
void * data
Definition: PtexReader.h:222
PtexReader::_pos
FilePos _pos
Definition: PtexReader.h:578
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
PtexReader::unpackedSize
int unpackedSize(FaceDataHeader fdh, int levelid, int faceid)
Definition: PtexReader.h:516
PtexReader::MetaData::_reader
PtexReader * _reader
Definition: PtexReader.h:262
PtexReader::MetaEdit
Definition: PtexReader.h:602
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:585
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition: PtexReader.h:588
PtexFaceData::tileRes
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
PtexUtils::max
static T max(T a, T b)
Definition: PtexUtils.h:119