Ptex: PtexReader.cpp Source File

Ptex

PtexReader.cpp
Go to the documentation of this file.
1/*
2PTEX SOFTWARE
3Copyright 2014 Disney Enterprises, Inc. All rights reserved
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
22Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34*/
35
36#include "PtexPlatform.h"
37#include <climits>
38#include <iostream>
39#include <sstream>
40#include <stdio.h>
41
42#include <libdeflate.h>
43
44#include "Ptexture.h"
45#include "PtexUtils.h"
46#include "PtexReader.h"
47
48namespace {
49 class TempErrorHandler : public PtexErrorHandler
50 {
51 std::string _error;
52 public:
53 virtual void reportError(const char* error) {
54 _error += error;
55 }
56 const std::string& getErrorString() const { return _error; }
57 };
58}
59
60 PTEX_NAMESPACE_BEGIN
61
62 PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
63{
64 PtexReader* reader = new PtexReader(premultiply, (PtexInputHandler*) 0, (PtexErrorHandler*) 0);
65 bool ok = reader->open(path, error);
66 if (!ok) {
67 reader->release();
68 return 0;
69 }
70 return reader;
71}
72
73
74PtexReader::PtexReader(bool premultiply, PtexInputHandler* io, PtexErrorHandler* err)
75 : _io(io ? io : &_defaultIo),
76 _err(err),
77 _premultiply(premultiply),
78 _ok(true),
79 _needToOpen(true),
80 _pendingPurge(false),
81 _fp(0),
82 _pos(0),
83 _pixelsize(0),
84 _constdata(0),
85 _metadata(0),
86 _baseMemUsed(sizeof(*this)),
87 _memUsed(_baseMemUsed),
88 _opens(0),
89 _blockReads(0)
90{
91 _decompressor = libdeflate_alloc_decompressor();
92}
93
94
95PtexReader::~PtexReader()
96{
97 closeFP();
98 if (_constdata) delete [] _constdata;
99 if (_metadata) delete _metadata;
100
101 for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
102 if (*i) delete *i;
103 }
104 libdeflate_free_decompressor(_decompressor);
105}
106
107 void PtexReader::prune()
108{
109 if (_metadata) { delete _metadata; _metadata = 0; }
110 for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
111 if (*i) { delete *i; *i = 0; }
112 }
113 _reductions.clear();
114 _memUsed = _baseMemUsed;
115}
116
117
118 void PtexReader::purge()
119{
120 // free all dynamic data
121 prune();
122 if (_constdata) {delete [] _constdata; _constdata = 0; }
123 std::vector<FaceInfo>().swap(_faceinfo);
124 std::vector<uint32_t>().swap(_rfaceids);
125 std::vector<LevelInfo>().swap(_levelinfo);
126 std::vector<FilePos>().swap(_levelpos);
127 std::vector<Level*>().swap(_levels);
128 {
129 AutoMutex locker(readlock);
130 closeFP();
131 }
132
133 // reset initial state
134 _ok = true;
135 _needToOpen = true;
136 _pendingPurge = false;
137 _memUsed = _baseMemUsed = sizeof(*this);
138}
139
140
141 bool PtexReader::open(const char* pathArg, Ptex::String& error)
142{
143 AutoMutex locker(readlock);
144 if (!needToOpen()) return false;
145
146 auto openError = [&](const std::string& msg) -> bool {
147 error = msg.c_str();
148 _ok = false;
149 closeFP();
150 return false;
151 };
152
153 if (!LittleEndian()) {
154 error = "Ptex library doesn't currently support big-endian cpu's";
155 return false;
156 }
157 _path = pathArg;
158 _fp = _io->open(pathArg);
159 if (!_fp) {
160 std::string errstr = "Can't open ptex file: ";
161 errstr += pathArg; errstr += "\n"; errstr += _io->lastError();
162 error = errstr.c_str();
163 _ok = false;
164 return false;
165 }
166 memset(&_header, 0, sizeof(_header));
167 readBlock(&_header, HeaderSize);
168 if (_header.magic != Magic) {
169 return openError(std::string("Not a ptex file: ") + pathArg);
170 }
171 if (_header.version != 1) {
172 std::stringstream s;
173 s << "Unsupported ptex file version (" << _header.version << "): " << pathArg;
174 return openError(s.str());
175 }
176 if (!(_header.meshtype == mt_triangle || _header.meshtype == mt_quad)) {
177 std::stringstream s;
178 s << "Invalid mesh type (" << _header.meshtype << "): " << pathArg;
179 return openError(s.str());
180 }
181 if (_header.datatype > dt_float) {
182 std::stringstream s;
183 s << "Invalid data type (" << _header.datatype << "): " << pathArg;
184 return openError(s.str());
185 }
186 if (_header.nchannels == 0) {
187 return openError(std::string("Invalid number of channels (0): ") + pathArg);
188 }
189 if (_header.nfaces == 0) {
190 return openError(std::string("Invalid number of faces (0): ") + pathArg);
191 }
192 if (_header.nlevels == 0) {
193 return openError(std::string("Invalid number of levels (0): ") + pathArg);
194 }
195 if (_header.faceinfosize == 0) {
196 return openError(std::string("Invalid face info size (0): ") + pathArg);
197 }
198 if (_header.levelinfosize != uint64_t(_header.nlevels) * LevelInfoSize) {
199 return openError(std::string("Inconsistent level info size: ") + pathArg);
200 }
201 _pixelsize = _header.pixelSize();
202
203 // Validate claimed uncompressed sizes against compressed sizes on disk.
204 // A valid deflate stream cannot expand beyond 1032x, so a header claiming
205 // a larger uncompressed size is invalid / corrupt.
206 static const uint64_t MaxDeflateExpansion = 1032;
207 const uint64_t pixelsize = uint64_t(_pixelsize);
208 if (uint64_t(_header.nfaces) * sizeof(FaceInfo)
209 > uint64_t(_header.faceinfosize) * MaxDeflateExpansion) {
210 return openError(std::string("Unreasonable face count: ") + pathArg);
211 }
212 if (uint64_t(_header.nfaces) * pixelsize
213 > uint64_t(_header.constdatasize) * MaxDeflateExpansion) {
214 return openError(std::string("Unreasonable constdata size: ") + pathArg);
215 }
216 if (uint64_t(_header.metadatamemsize)
217 > uint64_t(_header.metadatazipsize) * MaxDeflateExpansion) {
218 return openError(std::string("Unreasonable metadata size: ") + pathArg);
219 }
220 _errorPixel.resize(_pixelsize);
221
222 // install temp error handler to capture error (to return in error param)
223 TempErrorHandler tempErr;
224 PtexErrorHandler* prevErr = _err;
225 _err = &tempErr;
226
227 // read extended header
228 memset(&_extheader, 0, sizeof(_extheader));
229 readBlock(&_extheader, std::min(uint32_t(ExtHeaderSize), _header.extheadersize));
230
231 // compute offsets of various blocks
232 FilePos pos = HeaderSize + _header.extheadersize;
233 _faceinfopos = pos; pos += _header.faceinfosize;
234 _constdatapos = pos; pos += _header.constdatasize;
235 _levelinfopos = pos; pos += _header.levelinfosize;
236 _leveldatapos = pos; pos += _header.leveldatasize;
237 _metadatapos = pos; pos += _header.metadatazipsize;
238 pos += sizeof(uint64_t); // compatibility barrier
239 _lmdheaderpos = pos; pos += _extheader.lmdheaderzipsize;
240 _lmddatapos = pos; pos += _extheader.lmddatasize;
241
242 // read basic file info
243 readFaceInfo();
244 readConstData();
245 readLevelInfo();
246 _baseMemUsed = _memUsed;
247
248 // restore error handler
249 _err = prevErr;
250
251 // an error occurred while reading the file
252 if (!_ok) {
253 error = tempErr.getErrorString();
254 closeFP();
255 return 0;
256 }
257 AtomicStore(&_needToOpen, false);
258 return true;
259}
260
261 bool PtexReader::tryClose()
262{
263 if (_fp) {
264 if (!readlock.trylock()) return false;
265 closeFP();
266 readlock.unlock();
267 }
268 return true;
269}
270
271
272 void PtexReader::closeFP()
273{
274 if (_fp) {
275 _io->close(_fp);
276 _fp = 0;
277 }
278}
279
280
281 bool PtexReader::reopenFP()
282{
283 if (_fp) return true;
284
285 // we assume this is called lazily in a scope where readlock is already held
286 _fp = _io->open(_path.c_str());
287 if (!_fp) {
288 setIOError("Can't reopen");
289 return false;
290 }
291 _pos = 0;
292 Header headerval;
293 ExtHeader extheaderval;
294 readBlock(&headerval, HeaderSize);
295 memset(&extheaderval, 0, sizeof(extheaderval));
296 readBlock(&extheaderval, std::min(uint32_t(ExtHeaderSize), headerval.extheadersize));
297 if (0 != memcmp(&headerval, &_header, sizeof(headerval)) ||
298 0 != memcmp(&extheaderval, &_extheader, sizeof(extheaderval)))
299 {
300 setError("Header mismatch on reopen of");
301 return false;
302 }
303 logOpen();
304 return true;
305}
306
307
308 const Ptex::FaceInfo& PtexReader::getFaceInfo(int faceid)
309{
310 if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
311 return _faceinfo[faceid];
312
313 static Ptex::FaceInfo dummy;
314 return dummy;
315}
316
317
318 void PtexReader::readFaceInfo()
319{
320 if (_faceinfo.empty()) {
321 // read compressed face info block
322 seek(_faceinfopos);
323 uint32_t nfaces = _header.nfaces;
324 int64_t faceInfoSize64 = (int64_t)sizeof(FaceInfo) * nfaces;
325 if (faceInfoSize64 > INT_MAX) {
326 setError("PtexReader error: faceinfo size overflow");
327 return;
328 }
329 _faceinfo.resize(nfaces);
330 readZipBlock(&_faceinfo[0], _header.faceinfosize, (int)faceInfoSize64);
331
332 // generate rfaceids
333 _rfaceids.resize(nfaces);
334 std::vector<uint32_t> faceids_r(nfaces);
335 PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
336 &_rfaceids[0], &faceids_r[0]);
337 increaseMemUsed(nfaces * (sizeof(_faceinfo[0]) + sizeof(_rfaceids[0])));
338 }
339}
340
341
342
343 void PtexReader::readLevelInfo()
344{
345 if (_levelinfo.empty()) {
346 // read level info block
347 seek(_levelinfopos);
348 _levelinfo.resize(_header.nlevels);
349 readBlock(&_levelinfo[0], LevelInfoSize*_header.nlevels);
350
351 // initialize related data
352 _levels.resize(_header.nlevels);
353 _levelpos.resize(_header.nlevels);
354 FilePos pos = _leveldatapos;
355 for (int i = 0; i < _header.nlevels; i++) {
356 _levelpos[i] = pos;
357 pos += _levelinfo[i].leveldatasize;
358 }
359 increaseMemUsed(_header.nlevels * sizeof(_levelinfo[0]) + sizeof(_levels[0]) + sizeof(_levelpos[0]));
360 }
361}
362
363
364 void PtexReader::readConstData()
365{
366 if (!_constdata) {
367 // read compressed constant data block
368 seek(_constdatapos);
369 int64_t size64 = (int64_t)_pixelsize * _header.nfaces;
370 if (size64 > INT_MAX) {
371 setError("PtexReader error: constdata size overflow");
372 return;
373 }
374 int size = (int)size64;
375 _constdata = new uint8_t[size];
376 readZipBlock(_constdata, _header.constdatasize, size);
377 if (_premultiply && _header.hasAlpha())
378 PtexUtils::multalpha(_constdata, _header.nfaces, datatype(),
379 _header.nchannels, _header.alphachan);
380 increaseMemUsed(size);
381 }
382}
383
384
385 PtexMetaData* PtexReader::getMetaData()
386{
387 if (!_metadata) readMetaData();
388 return _metadata;
389}
390
391
392 PtexReader::MetaData::Entry*
393PtexReader::MetaData::getEntry(int index)
394{
395 if (index < 0 || index >= int(_entries.size())) {
396 return 0;
397 }
398
399 Entry* e = _entries[index];
400 if (!e->isLmd) {
401 // normal (small) meta data - just return directly
402 return e;
403 }
404
405 // large meta data - may not be read in yet
406 if (e->lmdData) {
407 // already in memory
408 return e;
409 }
410 else {
411 // not present, must read from file
412
413 // get read lock and make sure we still need to read
414 AutoMutex locker(_reader->readlock);
415 if (e->lmdData) {
416 return e;
417 }
418 // go ahead and read, keep local until finished
419 LargeMetaData* lmdData = new LargeMetaData(e->datasize);
420 e->data = (char*) lmdData->data();
421 _reader->increaseMemUsed(sizeof(LargeMetaData) + e->datasize);
422 _reader->seek(e->lmdPos);
423 _reader->readZipBlock(e->data, e->lmdZipSize, e->datasize);
424 // update entry
425 e->lmdData = lmdData;
426 return e;
427 }
428}
429
430
431 void PtexReader::readMetaData()
432{
433 // get read lock and make sure we still need to read
434 AutoMutex locker(readlock);
435 if (_metadata) {
436 return;
437 }
438
439 // allocate new meta data (keep local until fully initialized)
440 MetaData* newmeta = new MetaData(this);
441 size_t metaDataMemUsed = sizeof(MetaData);
442
443 // read primary meta data blocks
444 if (_header.metadatamemsize)
445 readMetaDataBlock(newmeta, _metadatapos,
446 _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
447
448 // read large meta data headers
449 if (_extheader.lmdheadermemsize)
450 readLargeMetaDataHeaders(newmeta, _lmdheaderpos,
451 _extheader.lmdheaderzipsize, _extheader.lmdheadermemsize, metaDataMemUsed);
452
453 // store meta data
454 AtomicStore(&_metadata, newmeta);
455 increaseMemUsed(newmeta->selfDataSize() + metaDataMemUsed);
456}
457
458
459 void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
460{
461 seek(pos);
462 // read from file
463 bool useNew = memsize > AllocaMax;
464 char* buff = useNew ? new char[memsize] : (char*)alloca(memsize);
465
466 if (readZipBlock(buff, zipsize, memsize)) {
467 // unpack data entries
468 char* ptr = buff;
469 char* end = ptr + memsize;
470 while (ptr < end) {
471 uint8_t keysize = *ptr++;
472 char* key = (char*)ptr; ptr += keysize;
473 key[keysize-1] = '\0';
474 uint8_t datatypeval = *ptr++;
475 uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
476 ptr += sizeof(datasize);
477 char* data = ptr; ptr += datasize;
478 metadata->addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
479 }
480 }
481 if (useNew) delete [] buff;
482}
483
484
485 void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
486{
487 seek(pos);
488 // read from file
489 bool useNew = memsize > AllocaMax;
490 char* buff = useNew ? new char [memsize] : (char*)alloca(memsize);
491
492 if (readZipBlock(buff, zipsize, memsize)) {
493 pos += zipsize;
494
495 // unpack data entries
496 char* ptr = buff;
497 char* end = ptr + memsize;
498 while (ptr < end) {
499 uint8_t keysize = *ptr++;
500 char* key = (char*)ptr; ptr += keysize;
501 uint8_t datatypeval = *ptr++;
502 uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
503 ptr += sizeof(datasize);
504 uint32_t zipsizeval; memcpy(&zipsizeval, ptr, sizeof(zipsizeval));
505 ptr += sizeof(zipsizeval);
506 metadata->addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
507 pos += zipsizeval;
508 }
509 }
510 if (useNew) delete [] buff;
511}
512
513
514 bool PtexReader::readBlock(void* data, int size)
515{
516 assert(_fp && size >= 0);
517 if (!_fp || size < 0) return false;
518 int result = (int)_io->read(data, size, _fp);
519 if (result == size) {
520 _pos += size;
521 return true;
522 }
523 setIOError("PtexReader error: read failed");
524 return false;
525}
526
527
528 bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
529{
530 if (!_ok || zipsize < 0 || unzipsize < 0) return false;
531 std::vector<std::byte> compressedBuffer(zipsize);
532 if (!readBlock(compressedBuffer.data(), compressedBuffer.size())) {
533 return false;
534 }
535 size_t bytesDecompressed{0};
536 if (libdeflate_zlib_decompress(_decompressor, compressedBuffer.data(), compressedBuffer.size(),
537 data, unzipsize, &bytesDecompressed) != 0 ||
538 bytesDecompressed != size_t(unzipsize))
539 {
540 setError("PtexReader error: unzip failed, file corrupt");
541 return false;
542 }
543 return true;
544}
545
546
547 void PtexReader::readLevel(int levelid, Level*& level)
548{
549 // get read lock and make sure we still need to read
550 AutoMutex locker(readlock);
551 if (level) {
552 return;
553 }
554
555 // go ahead and read the level
556 LevelInfo& l = _levelinfo[levelid];
557
558 // keep new level local until finished
559 Level* newlevel = new Level(l.nfaces);
560
561 // read level header
562 seek(_levelpos[levelid]);
563 readZipBlock(&newlevel->fdh[0], l.levelheadersize, FaceDataHeaderSize * l.nfaces);
564
565 // compute face offsets
566 std::vector<uint32_t> largeFaces;
567 FilePos offset = tell();
568 for (uint32_t f = 0; f < l.nfaces; f++) {
569 newlevel->offsets[f] = offset;
570 if (!newlevel->fdh[f].isLargeFace()) {
571 offset += newlevel->fdh[f].blocksize();
572 } else {
573 // large faces have a 64-bit size, stored after the level header
574 largeFaces.push_back(f);
575 }
576 }
577
578 // update offsets to account for large faces
579 if (!largeFaces.empty()) {
580 int nlarge = int(largeFaces.size());
581 // read large face header (64-bit sizes of large faces)
582 std::vector<size_t> largeFaceHeader(nlarge);
583 size_t largeFaceHeaderSize = sizeof(size_t) * nlarge;
584 readBlock(largeFaceHeader.data(), largeFaceHeaderSize);
585
586 // update offsets
587 size_t extraOffset = largeFaceHeaderSize;
588 uint32_t f = 0;
589 for (int i = 0; i < nlarge; i++) {
590 uint32_t lf = largeFaces[i];
591 while (f <= lf) {
592 newlevel->offsets[f++] += extraOffset;
593 }
594 extraOffset += largeFaceHeader[i];
595 }
596 while (f < l.nfaces) {
597 newlevel->offsets[f++] += extraOffset;
598 }
599 }
600
601 // don't assign to result until level data is fully initialized
602 AtomicStore(&level, newlevel);
603 increaseMemUsed(level->memUsed());
604}
605
606
607 void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
608{
609 FaceData*& face = level->faces[faceid];
610 FaceDataHeader fdh = level->fdh[faceid];
611 readFaceData(level->offsets[faceid], fdh, res, levelid, face);
612}
613
614
615 void PtexReader::TiledFace::readTile(int tile, FaceData*& data)
616{
617 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
618}
619
620
621 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
622 FaceData*& face)
623{
624 AutoMutex locker(readlock);
625 if (face) {
626 return;
627 }
628
629 // keep new face local until fully initialized
630 FaceData* newface = 0;
631 size_t newMemUsed = 0;
632
633 seek(pos);
634 switch (fdh.encoding()) {
635 case enc_constant:
636 {
637 ConstantFace* cf = new ConstantFace(_pixelsize);
638 newface = cf;
639 newMemUsed = sizeof(ConstantFace) + _pixelsize;
640 readBlock(cf->data(), _pixelsize);
641 if (levelid==0 && _premultiply && _header.hasAlpha())
642 PtexUtils::multalpha(cf->data(), 1, datatype(),
643 _header.nchannels, _header.alphachan);
644 }
645 break;
646 case enc_tiled:
647 {
648 Res tileres;
649 readBlock(&tileres, sizeof(tileres));
650 uint32_t tileheadersize;
651 readBlock(&tileheadersize, sizeof(tileheadersize));
652 TiledFace* tf = new TiledFace(this, res, tileres, levelid);
653 newface = tf;
654 newMemUsed = tf->memUsed();
655 readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
656 computeFaceTileOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
657 }
658 break;
659 case enc_zipped:
660 case enc_diffzipped:
661 {
662 int uw = res.u(), vw = res.v();
663 int npixels = uw * vw;
664 int unpackedSize = _pixelsize * npixels;
665 PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
666 newface = pf;
667 newMemUsed = sizeof(PackedFace) + unpackedSize;
668 bool useNew = unpackedSize > AllocaMax;
669 char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
670 readZipBlock(tmp, fdh.blocksize(), unpackedSize);
671 if (fdh.encoding() == enc_diffzipped)
672 PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
673 PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
674 pf->data(), uw * _pixelsize,
675 datatype(), _header.nchannels);
676 if (levelid==0 && _premultiply && _header.hasAlpha())
677 PtexUtils::multalpha(pf->data(), npixels, datatype(),
678 _header.nchannels, _header.alphachan);
679 if (useNew) delete [] tmp;
680 }
681 break;
682 }
683
684 if (!newface) newface = errorData();
685
686 AtomicStore(&face, newface);
687 increaseMemUsed(newMemUsed);
688}
689
690
691 void PtexReader::getData(int faceid, void* buffer, int stride)
692{
693 const FaceInfo& f = getFaceInfo(faceid);
694 getData(faceid, buffer, stride, f.res);
695}
696
697
698 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
699{
700 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
701 PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
702 return;
703 }
704
705 // note - all locking is handled in called getData methods
706 int resu = res.u(), resv = res.v();
707 int rowlen = _pixelsize * resu;
708 if (stride == 0) stride = rowlen;
709
710 PtexPtr<PtexFaceData> d ( getData(faceid, res) );
711 if (d->isConstant()) {
712 // fill dest buffer with pixel value
713 PtexUtils::fill(d->getData(), buffer, stride,
714 resu, resv, _pixelsize);
715 }
716 else if (d->isTiled()) {
717 // loop over tiles
718 Res tileres = d->tileRes();
719 int ntilesu = res.ntilesu(tileres);
720 int ntilesv = res.ntilesv(tileres);
721 int tileures = tileres.u();
722 int tilevres = tileres.v();
723 int tilerowlen = _pixelsize * tileures;
724 int tile = 0;
725 char* dsttilerow = (char*) buffer;
726 for (int i = 0; i < ntilesv; i++) {
727 char* dsttile = dsttilerow;
728 for (int j = 0; j < ntilesu; j++) {
729 PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
730 if (t->isConstant())
731 PtexUtils::fill(t->getData(), dsttile, stride,
732 tileures, tilevres, _pixelsize);
733 else
734 PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
735 tilevres, tilerowlen);
736 dsttile += tilerowlen;
737 }
738 dsttilerow += stride * tilevres;
739 }
740 }
741 else {
742 PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
743 }
744}
745
746
747 PtexFaceData* PtexReader::getData(int faceid)
748{
749 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
750 return errorData(/*deleteOnRelease*/ true);
751 }
752
753 FaceInfo& fi = _faceinfo[faceid];
754 if (fi.isConstant() || fi.res == 0) {
755 return new ConstDataPtr(getConstantData(faceid), _pixelsize);
756 }
757
758 // get level zero (full) res face
759 Level* level = getLevel(0);
760 FaceData* face = getFace(0, level, faceid, fi.res);
761 return face;
762}
763
764
765 PtexFaceData* PtexReader::getData(int faceid, Res res)
766{
767 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
768 return errorData(/*deleteOnRelease*/ true);
769 }
770
771 FaceInfo& fi = _faceinfo[faceid];
772 if (fi.isConstant() || res == 0) {
773 return new ConstDataPtr(getConstantData(faceid), _pixelsize);
774 }
775
776 // determine how many reduction levels are needed
777 int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
778
779 if (redu == 0 && redv == 0) {
780 // no reduction - get level zero (full) res face
781 Level* level = getLevel(0);
782 FaceData* face = getFace(0, level, faceid, res);
783 return face;
784 }
785
786 if (redu == redv) {
787 // reduction is symmetric and non-negative
788 // => access data from reduction level (if present)
789 int levelid = redu;
790 if (size_t(levelid) < _levels.size()) {
791 Level* level = getLevel(levelid);
792
793 // get reduction face id
794 int rfaceid = _rfaceids[faceid];
795
796 // get the face data (if present)
797 FaceData* face = 0;
798 if (size_t(rfaceid) < level->faces.size()) {
799 face = getFace(levelid, level, rfaceid, res);
800 }
801 if (face) {
802 return face;
803 }
804 }
805 }
806
807 // dynamic reduction required - look in dynamic reduction cache
808 ReductionKey key(faceid, res);
809 FaceData* face = _reductions.get(key);
810 if (face) {
811 return face;
812 }
813
814 // not found, generate new reduction
815 FaceData *newface = 0;
816 size_t newMemUsed = 0;
817
818 if (res.ulog2 < 0 || res.vlog2 < 0) {
819 std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
820 newface = errorData();
821 }
822 else if (redu < 0 || redv < 0) {
823 std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
824 newface = errorData();
825 }
826 else if (_header.meshtype == mt_triangle)
827 {
828 if (redu != redv) {
829 std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
830 newface = errorData();
831 }
832 else {
833 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
834 FaceData* src = static_cast<FaceData*>(psrc.get());
835 newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
836 }
837 }
838 else {
839 // determine which direction to blend
840 bool blendu;
841 if (redu == redv) {
842 // for symmetric face blends, alternate u and v blending
843 blendu = (res.ulog2 & 1);
844 }
845 else blendu = redu > redv;
846
847 if (blendu) {
848 // get next-higher u-res and reduce in u
849 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
850 FaceData* src = static_cast<FaceData*>(psrc.get());
851 newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
852 }
853 else {
854 // get next-higher v-res and reduce in v
855 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
856 FaceData* src = static_cast<FaceData*>(psrc.get());
857 newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
858 }
859 }
860
861 size_t tableNewMemUsed = 0;
862 face = _reductions.tryInsert(key, newface, tableNewMemUsed);
863 if (face != newface) {
864 delete newface;
865 }
866 else {
867 increaseMemUsed(newMemUsed + tableNewMemUsed);
868 }
869 return face;
870}
871
872
873 void PtexReader::getPixel(int faceid, int u, int v,
874 float* result, int firstchan, int nchannelsArg)
875{
876 memset(result, 0, sizeof(*result)*nchannelsArg);
877
878 // clip nchannels against actual number available
879 nchannelsArg = std::min(nchannelsArg, _header.nchannels-firstchan);
880 if (nchannelsArg <= 0) return;
881
882 // get raw pixel data
883 void* pixel;
884 if (faceid >= 0 && size_t(faceid) < _header.nfaces && _faceinfo[faceid].isConstant()) {
885 pixel = getConstantData(faceid);
886 }
887 else {
888 PtexPtr<PtexFaceData> data ( getData(faceid) );
889 pixel = alloca(_pixelsize);
890 data->getPixel(u, v, pixel);
891 }
892
893 // adjust for firstchan offset
894 int datasize = DataSize(datatype());
895 if (firstchan)
896 pixel = (char*) pixel + datasize * firstchan;
897
898 // convert/copy to result as needed
899 if (datatype() == dt_float)
900 memcpy(result, pixel, datasize * nchannelsArg);
901 else
902 ConvertToFloat(result, pixel, datatype(), nchannelsArg);
903}
904
905
906 void PtexReader::getPixel(int faceid, int u, int v,
907 float* result, int firstchan, int nchannelsArg,
908 Ptex::Res res)
909{
910 memset(result, 0, sizeof(*result)*nchannelsArg);
911
912 // clip nchannels against actual number available
913 nchannelsArg = std::min(nchannelsArg, _header.nchannels-firstchan);
914 if (nchannelsArg <= 0) return;
915
916 // get raw pixel data
917 void* pixel;
918 if (faceid >= 0 && size_t(faceid) < _header.nfaces && _faceinfo[faceid].isConstant()) {
919 pixel = getConstantData(faceid);
920 }
921 else {
922 PtexPtr<PtexFaceData> data ( getData(faceid, res) );
923 pixel = alloca(_pixelsize);
924 data->getPixel(u, v, pixel);
925 }
926
927 // adjust for firstchan offset
928 int datasize = DataSize(datatype());
929 if (firstchan)
930 pixel = (char*) pixel + datasize * firstchan;
931
932 // convert/copy to result as needed
933 if (datatype() == dt_float)
934 memcpy(result, pixel, datasize * nchannelsArg);
935 else
936 ConvertToFloat(result, pixel, datatype(), nchannelsArg);
937}
938
939
940 void PtexReader::getCompressedData(int faceid, int levelid, FaceDataHeader& fdh, std::vector<std::byte>& data)
941{
942 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces || size_t(levelid) >= _levels.size()) {
943 return;
944 }
945
946 Level* level = getLevel(levelid);
947 int rfaceid = levelid == 0 ? faceid : _rfaceids[faceid];
948 fdh = level->fdh[rfaceid];
949 FilePos offset = level->offsets[rfaceid];
950 size_t size{0};
951 if (!fdh.isLargeFace()) {
952 size = fdh.blocksize();
953 } else if (fdh.encoding() == enc_tiled) {
954 // read tiled face header
955 seek(offset);
956 FaceInfo& fi = _faceinfo[faceid];
957 Res level_res(fi.res.ulog2 - levelid, fi.res.vlog2 - levelid);
958 Res tileres;
959 readBlock(&tileres, sizeof(tileres));
960 uint32_t tileheadersize;
961 readBlock(&tileheadersize, sizeof(tileheadersize));
962 int ntiles = level_res.ntiles(tileres);
963 std::vector<FaceDataHeader> tiledFace_fdh(ntiles);
964 readZipBlock(&tiledFace_fdh[0], tileheadersize, FaceDataHeaderSize * ntiles);
965
966 // sum total size of header and tiles
967 size = sizeof(tileres) + sizeof(tileheadersize) + tileheadersize;
968 for (auto fdh : tiledFace_fdh) {
969 size += fdh.blocksize();
970 }
971 }
972
973 // read compressed face data
974 seek(offset);
975 data.resize(size);
976 readBlock(data.data(), size);
977}
978
979
980 PtexReader::FaceData*
981PtexReader::PackedFace::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
982 size_t& newMemUsed)
983{
984 // allocate a new face and reduce image
985 DataType dt = r->datatype();
986 int nchan = r->nchannels();
987 int memsize = _pixelsize * newres.size64();
988 PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
989 newMemUsed = sizeof(PackedFace) + memsize;
990 // reduce and copy into new face
991 reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
992 pf->_data, _pixelsize * newres.u(), dt, nchan);
993 return pf;
994}
995
996
997
998 PtexReader::FaceData* PtexReader::ConstantFace::reduce(PtexReader*, Res, PtexUtils::ReduceFn, size_t& newMemUsed)
999{
1000 // must make a new constant face (even though it's identical to this one)
1001 // because it will be owned by a different reduction level
1002 // and will therefore have a different parent
1003 ConstantFace* pf = new ConstantFace(_pixelsize);
1004 newMemUsed = sizeof(ConstantFace) + _pixelsize;
1005 memcpy(pf->_data, _data, _pixelsize);
1006 return pf;
1007}
1008
1009
1010 PtexReader::FaceData*
1011PtexReader::TiledFaceBase::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
1012 size_t& newMemUsed)
1013{
1014 /* Tiled reductions should generally only be anisotropic (just u
1015 or v, not both) since isotropic reductions are precomputed and
1016 stored on disk. (This function should still work for isotropic
1017 reductions though.)
1018
1019 In the anisotropic case, the number of tiles should be kept the
1020 same along the direction not being reduced in order to preserve
1021 the laziness of the file access. In contrast, if reductions
1022 were not tiled, then any reduction would read all the tiles and
1023 defeat the purpose of tiling.
1024 */
1025
1026 // keep new face local until fully initialized
1027 FaceData* newface = 0;
1028
1029 // don't tile triangle reductions (too complicated)
1030 Res newtileres;
1031 bool isTriangle = r->_header.meshtype == mt_triangle;
1032 if (isTriangle) {
1033 newtileres = newres;
1034 }
1035 else {
1036 // propagate the tile res to the reduction
1037 newtileres = _tileres;
1038 // but make sure tile isn't larger than the new face!
1039 if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1040 if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1041 }
1042
1043
1044 // determine how many tiles we will have on the reduction
1045 int newntiles = newres.ntiles(newtileres);
1046
1047 if (newntiles == 1) {
1048 // no need to keep tiling, reduce tiles into a single face
1049 // first, get all tiles and check if they are constant (with the same value)
1050 PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1051 bool allConstant = true;
1052 for (int i = 0; i < _ntiles; i++) {
1053 PtexFaceData* tile = tiles[i] = getTile(i);
1054 allConstant = (allConstant && tile->isConstant() &&
1055 (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1056 _pixelsize))));
1057 }
1058 if (allConstant) {
1059 // allocate a new constant face
1060 newface = new ConstantFace(_pixelsize);
1061 memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1062 newMemUsed = sizeof(ConstantFace) + _pixelsize;
1063 }
1064 else if (isTriangle) {
1065 // reassemble all tiles into temporary contiguous image
1066 // (triangle reduction doesn't work on tiles)
1067 int tileures = _tileres.u();
1068 int tilevres = _tileres.v();
1069 int sstride = _pixelsize * tileures;
1070 int dstride = sstride * _ntilesu;
1071 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1072
1073 char* tmp = new char [_ntiles * _tileres.size64() * _pixelsize];
1074 char* tmpptr = tmp;
1075 for (int i = 0; i < _ntiles;) {
1076 PtexFaceData* tile = tiles[i];
1077 if (tile->isConstant())
1078 PtexUtils::fill(tile->getData(), tmpptr, dstride,
1079 tileures, tilevres, _pixelsize);
1080 else
1081 PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1082 i++;
1083 tmpptr += (i%_ntilesu) ? sstride : dstepv;
1084 }
1085
1086 // allocate a new packed face
1087 int memsize = _pixelsize * newres.size64();
1088 newface = new PackedFace(newres, _pixelsize, memsize);
1089 newMemUsed = sizeof(PackedFace) + memsize;
1090 // reduce and copy into new face
1091 reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1092 newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1093
1094 delete [] tmp;
1095 }
1096 else {
1097 // allocate a new packed face
1098 int memsize = _pixelsize * newres.size64();
1099 newface = new PackedFace(newres, _pixelsize, memsize);
1100 newMemUsed = sizeof(PackedFace) + memsize;
1101
1102 int tileures = _tileres.u();
1103 int tilevres = _tileres.v();
1104 int sstride = _pixelsize * tileures;
1105 int dstride = _pixelsize * newres.u();
1106 int dstepu = dstride/_ntilesu;
1107 int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1108
1109 char* dst = (char*) newface->getData();
1110 for (int i = 0; i < _ntiles;) {
1111 PtexFaceData* tile = tiles[i];
1112 if (tile->isConstant())
1113 PtexUtils::fill(tile->getData(), dst, dstride,
1114 newres.u()/_ntilesu, newres.v()/_ntilesv,
1115 _pixelsize);
1116 else
1117 reducefn(tile->getData(), sstride, tileures, tilevres,
1118 dst, dstride, _dt, _nchan);
1119 i++;
1120 dst += (i%_ntilesu) ? dstepu : dstepv;
1121 }
1122 }
1123 // release the tiles
1124 for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1125 }
1126 else {
1127 // otherwise, tile the reduced face
1128 TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
1129 newface = tf;
1130 newMemUsed = tf->memUsed();
1131 }
1132 return newface;
1133}
1134
1135
1136 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1137{
1138 int tileu = ui >> _tileres.ulog2;
1139 int tilev = vi >> _tileres.vlog2;
1140 PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1141 tile->getPixel(ui - (tileu<<_tileres.ulog2),
1142 vi - (tilev<<_tileres.vlog2), result);
1143}
1144
1145
1146
1147 PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
1148{
1149 FaceData*& face = _tiles[tile];
1150 if (face) {
1151 return face;
1152 }
1153
1154 // first, get all parent tiles for this tile
1155 // and check if they are constant (with the same value)
1156 int pntilesu = _parentface->ntilesu();
1157 int pntilesv = _parentface->ntilesv();
1158 int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1159 int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1160
1161 int ntilesval = nu*nv; // num parent tiles for this tile
1162 PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
1163 bool allConstant = true;
1164 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1165 for (int i = 0; i < ntilesval;) {
1166 PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
1167 allConstant = (allConstant && tileval->isConstant() &&
1168 (i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
1169 _pixelsize))));
1170 i++;
1171 ptile += (i%nu)? 1 : pntilesu - nu + 1;
1172 }
1173
1174 FaceData* newface = 0;
1175 size_t newMemUsed = 0;
1176 if (allConstant) {
1177 // allocate a new constant face
1178 newface = new ConstantFace(_pixelsize);
1179 newMemUsed = sizeof(ConstantFace) + _pixelsize;
1180 memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1181 }
1182 else {
1183 // allocate a new packed face for the tile
1184 int memsize = _pixelsize*_tileres.size64();
1185 newface = new PackedFace(_tileres, _pixelsize, memsize);
1186 newMemUsed = sizeof(PackedFace) + memsize;
1187
1188 // generate reduction from parent tiles
1189 int ptileures = _parentface->tileres().u();
1190 int ptilevres = _parentface->tileres().v();
1191 int sstride = ptileures * _pixelsize;
1192 int dstride = _tileres.u() * _pixelsize;
1193 int dstepu = dstride/nu;
1194 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1195
1196 char* dst = (char*) newface->getData();
1197 for (int i = 0; i < ntilesval;) {
1198 PtexFaceData* tileval = tiles[i];
1199 if (tileval->isConstant())
1200 PtexUtils::fill(tileval->getData(), dst, dstride,
1201 _tileres.u()/nu, _tileres.v()/nv,
1202 _pixelsize);
1203 else
1204 _reducefn(tileval->getData(), sstride, ptileures, ptilevres,
1205 dst, dstride, _dt, _nchan);
1206 i++;
1207 dst += (i%nu) ? dstepu : dstepv;
1208 }
1209 }
1210
1211 if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
1212 delete newface;
1213 }
1214 else {
1215 _reader->increaseMemUsed(newMemUsed);
1216 }
1217
1218 return face;
1219}
1220
1221 PTEX_NAMESPACE_END
Magic
const uint32_t Magic
Definition PtexIO.h:99
FaceDataHeaderSize
const int FaceDataHeaderSize
Definition PtexIO.h:103
ExtHeaderSize
const int ExtHeaderSize
Definition PtexIO.h:101
AllocaMax
const int AllocaMax
Definition PtexIO.h:109
HeaderSize
const int HeaderSize
Definition PtexIO.h:100
LevelInfoSize
const int LevelInfoSize
Definition PtexIO.h:102
LittleEndian
bool LittleEndian()
Definition PtexIO.h:112
enc_diffzipped
@ enc_diffzipped
Definition PtexIO.h:81
enc_zipped
@ enc_zipped
Definition PtexIO.h:81
enc_constant
@ enc_constant
Definition PtexIO.h:81
enc_tiled
@ enc_tiled
Definition PtexIO.h:81
AutoMutex
AutoLock< Mutex > AutoMutex
Definition PtexMutex.h:51
PtexPlatform.h
Platform-specific classes, functions, and includes.
FilePos
off_t FilePos
Definition PtexPlatform.h:101
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition PtexPlatform.h:286
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition PtexPlatform.h:280
PtexReader.h
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition PtexUtils.cpp:123
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
Mutex::trylock
bool trylock()
Definition PtexPlatform.h:144
Mutex::unlock
void unlock()
Definition PtexPlatform.h:145
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition Ptexture.h:667
PtexFaceData
Per-face texture data accessor.
Definition Ptexture.h:409
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
PtexHashMap::clear
void clear()
Definition PtexHashMap.h:187
PtexHashMap::get
Value get(Key &key) const
Definition PtexHashMap.h:197
PtexHashMap::tryInsert
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition PtexHashMap.h:220
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition Ptexture.h:628
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexMetaData
Meta data accessor.
Definition Ptexture.h:331
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition Ptexture.h:1067
PtexPtr::get
T * get() const
Get pointer value.
Definition Ptexture.h:1083
PtexReader::ConstDataPtr::ConstDataPtr
ConstDataPtr(void *data, int pixelsize)
Definition PtexReader.h:350
PtexReader::ConstantFace
Definition PtexReader.h:404
PtexReader::ConstantFace::ConstantFace
ConstantFace(int pixelsize)
Definition PtexReader.h:406
PtexReader::ConstantFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:998
PtexReader::FaceData
Definition PtexReader.h:368
PtexReader::FaceData::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
PtexReader::FaceData::_res
Res _res
Definition PtexReader.h:377
PtexReader::FaceData::FaceData
FaceData(Res resArg)
Definition PtexReader.h:370
PtexReader::Level
Definition PtexReader.h:523
PtexReader::Level::Level
Level(int nfaces)
Definition PtexReader.h:529
PtexReader::Level::offsets
std::vector< FilePos > offsets
Definition PtexReader.h:526
PtexReader::Level::fdh
std::vector< FaceDataHeader > fdh
Definition PtexReader.h:525
PtexReader::Level::faces
std::vector< FaceData * > faces
Definition PtexReader.h:527
PtexReader::Level::memUsed
size_t memUsed()
Definition PtexReader.h:540
PtexReader::MetaData::LargeMetaData
Definition PtexReader.h:276
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition PtexReader.h:281
PtexReader::MetaData::LargeMetaData::LargeMetaData
LargeMetaData(int size)
Definition PtexReader.h:278
PtexReader::MetaData
Definition PtexReader.h:123
PtexReader::MetaData::selfDataSize
size_t selfDataSize()
Definition PtexReader.h:269
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition PtexReader.h:249
PtexReader::MetaData::MetaData
MetaData(PtexReader *reader)
Definition PtexReader.h:125
PtexReader::MetaData::_reader
PtexReader * _reader
Definition PtexReader.h:341
PtexReader::MetaData::addLmdEntry
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize, size_t &metaDataMemUsed)
Definition PtexReader.h:258
PtexReader::MetaData::getEntry
Entry * getEntry(int index)
Definition PtexReader.cpp:393
PtexReader::MetaData::_entries
std::vector< Entry * > _entries
Definition PtexReader.h:344
PtexReader::PackedFace
Definition PtexReader.h:380
PtexReader::PackedFace::data
void * data()
Definition PtexReader.h:385
PtexReader::PackedFace::PackedFace
PackedFace(Res resArg, int pixelsize, int size)
Definition PtexReader.h:382
PtexReader::PackedFace::_pixelsize
int _pixelsize
Definition PtexReader.h:400
PtexReader::PackedFace::_data
char * _data
Definition PtexReader.h:401
PtexReader::PackedFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:981
PtexReader::ReductionKey
Definition PtexReader.h:675
PtexReader::TiledFaceBase::_tiles
std::vector< FaceData * > _tiles
Definition PtexReader.h:469
PtexReader::TiledFaceBase::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition PtexReader.cpp:1011
PtexReader::TiledFaceBase::_dt
DataType _dt
Definition PtexReader.h:463
PtexReader::TiledFaceBase::getData
virtual void * getData()
Access the data from this data block.
Definition PtexReader.h:443
PtexReader::TiledFaceBase::_ntilesv
int _ntilesv
Definition PtexReader.h:466
PtexReader::TiledFaceBase::_ntilesu
int _ntilesu
Definition PtexReader.h:465
PtexReader::TiledFaceBase::_nchan
int _nchan
Definition PtexReader.h:464
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition PtexReader.h:467
PtexReader::TiledFaceBase::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition PtexReader.h:440
PtexReader::TiledFaceBase::_tileres
Res _tileres
Definition PtexReader.h:462
PtexReader::TiledFaceBase::_pixelsize
int _pixelsize
Definition PtexReader.h:468
PtexReader::TiledFaceBase::_reader
PtexReader * _reader
Definition PtexReader.h:461
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition PtexReader.cpp:1136
PtexReader::TiledFace
Definition PtexReader.h:473
PtexReader::TiledFace::_fdh
std::vector< FaceDataHeader > _fdh
Definition PtexReader.h:496
PtexReader::TiledFace::TiledFace
TiledFace(PtexReader *reader, Res resArg, Res tileresArg, int levelid)
Definition PtexReader.h:475
PtexReader::TiledFace::_levelid
int _levelid
Definition PtexReader.h:495
PtexReader::TiledFace::memUsed
size_t memUsed()
Definition PtexReader.h:489
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition PtexReader.cpp:615
PtexReader::TiledFace::_offsets
std::vector< FilePos > _offsets
Definition PtexReader.h:497
PtexReader::TiledReducedFace
Definition PtexReader.h:501
PtexReader::TiledReducedFace::_parentface
TiledFaceBase * _parentface
Definition PtexReader.h:518
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition PtexReader.cpp:1147
PtexReader::TiledReducedFace::_reducefn
PtexUtils::ReduceFn * _reducefn
Definition PtexReader.h:519
PtexReader::TiledReducedFace::memUsed
size_t memUsed()
Definition PtexReader.h:515
PtexReader::TiledReducedFace::TiledReducedFace
TiledReducedFace(PtexReader *reader, Res resArg, Res tileresArg, TiledFaceBase *parentface, PtexUtils::ReduceFn reducefn)
Definition PtexReader.h:503
PtexReader
Definition PtexReader.h:53
PtexReader::readLevelInfo
void readLevelInfo()
Definition PtexReader.cpp:343
PtexReader::_reductions
ReductionMap _reductions
Definition PtexReader.h:703
PtexReader::reopenFP
bool reopenFP()
Definition PtexReader.cpp:281
PtexReader::datatype
DataType datatype() const
Definition PtexReader.h:116
PtexReader::_premultiply
bool _premultiply
Definition PtexReader.h:649
PtexReader::_constdatapos
FilePos _constdatapos
Definition PtexReader.h:659
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:459
PtexReader::getConstantData
virtual void * getConstantData(int faceid) final
Access the constant (or average) data value for a given face.
Definition PtexReader.h:108
PtexReader::readFaceInfo
void readFaceInfo()
Definition PtexReader.cpp:318
PtexReader::_path
std::string _path
Definition PtexReader.h:655
PtexReader::_constdata
uint8_t * _constdata
Definition PtexReader.h:666
PtexReader::_levelpos
std::vector< FilePos > _levelpos
Definition PtexReader.h:672
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:873
PtexReader::setIOError
void setIOError(const char *error)
Definition PtexReader.h:564
PtexReader::_opens
volatile size_t _opens
Definition PtexReader.h:709
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition PtexReader.h:57
PtexReader::increaseMemUsed
void increaseMemUsed(size_t amount)
Definition PtexReader.h:72
PtexReader::computeFaceTileOffsets
void computeFaceTileOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition PtexReader.h:613
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.h:591
PtexReader::purge
void purge()
Definition PtexReader.cpp:118
PtexReader::tell
FilePos tell()
Definition PtexReader.h:569
PtexReader::getLevel
Level * getLevel(int levelid)
Definition PtexReader.h:584
PtexReader::errorData
FaceData * errorData(bool deleteOnRelease=false)
Definition PtexReader.h:608
PtexReader::~PtexReader
virtual ~PtexReader()
Definition PtexReader.cpp:95
PtexReader::_needToOpen
bool _needToOpen
Definition PtexReader.h:651
PtexReader::readConstData
void readConstData()
Definition PtexReader.cpp:364
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition PtexReader.cpp:385
PtexReader::needToOpen
bool needToOpen() const
Definition PtexReader.h:58
PtexReader::_extheader
ExtHeader _extheader
Definition PtexReader.h:657
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition PtexReader.h:661
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition PtexReader.cpp:691
PtexReader::_err
PtexErrorHandler * _err
Definition PtexReader.h:648
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition PtexReader.h:658
PtexReader::_levelinfo
std::vector< LevelInfo > _levelinfo
Definition PtexReader.h:671
PtexReader::readBlock
bool readBlock(void *data, int size)
Definition PtexReader.cpp:514
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition PtexReader.cpp:74
PtexReader::_io
PtexInputHandler * _io
Definition PtexReader.h:647
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition PtexReader.cpp:308
PtexReader::_metadatapos
FilePos _metadatapos
Definition PtexReader.h:662
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition PtexReader.cpp:485
PtexReader::closeFP
void closeFP()
Definition PtexReader.cpp:272
PtexReader::_pixelsize
int _pixelsize
Definition PtexReader.h:665
PtexReader::_pendingPurge
bool _pendingPurge
Definition PtexReader.h:652
PtexReader::readlock
Mutex readlock
Definition PtexReader.h:645
PtexReader::setError
void setError(const char *error, bool ioError=false)
Definition PtexReader.h:549
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid, Res res)
Definition PtexReader.cpp:607
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition PtexReader.h:660
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition PtexReader.h:663
PtexReader::nchannels
int nchannels() const
Definition PtexReader.h:117
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition PtexReader.h:664
PtexReader::prune
void prune()
Definition PtexReader.cpp:107
PtexReader::_rfaceids
std::vector< uint32_t > _rfaceids
Definition PtexReader.h:670
PtexReader::_memUsed
volatile size_t _memUsed
Definition PtexReader.h:708
PtexReader::_defaultIo
DefaultInputHandler _defaultIo
Definition PtexReader.h:646
PtexReader::_blockReads
volatile size_t _blockReads
Definition PtexReader.h:710
PtexReader::_header
Header _header
Definition PtexReader.h:656
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition PtexReader.cpp:621
PtexReader::_decompressor
libdeflate_decompressor * _decompressor
Definition PtexReader.h:706
PtexReader::seek
void seek(FilePos pos)
Definition PtexReader.h:570
PtexReader::_metadata
MetaData * _metadata
Definition PtexReader.h:667
PtexReader::_levels
std::vector< Level * > _levels
Definition PtexReader.h:673
PtexReader::_baseMemUsed
size_t _baseMemUsed
Definition PtexReader.h:707
PtexReader::_faceinfo
std::vector< FaceInfo > _faceinfo
Definition PtexReader.h:669
PtexReader::pixelsize
int pixelsize() const
Definition PtexReader.h:118
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition PtexReader.h:653
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition PtexReader.cpp:528
PtexReader::getCompressedData
void getCompressedData(int faceid, int level, FaceDataHeader &fdh, std::vector< std::byte > &data)
Definition PtexReader.cpp:940
PtexReader::readMetaData
void readMetaData()
Definition PtexReader.cpp:431
PtexReader::logOpen
void logOpen()
Definition PtexReader.h:73
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition PtexReader.cpp:547
PtexReader::_errorPixel
std::vector< char > _errorPixel
Definition PtexReader.h:704
PtexReader::_pos
FilePos _pos
Definition PtexReader.h:654
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition PtexReader.cpp:141
PtexReader::tryClose
bool tryClose()
Definition PtexReader.cpp:261
PtexReader::_ok
bool _ok
Definition PtexReader.h:650
PtexTexture
Interface for reading data from a ptex file.
Definition Ptexture.h:460
PtexTexture::path
virtual const char * path()=0
Path that file was opened with.
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition PtexReader.cpp:62
Ptex::String
Memory-managed string.
Definition Ptexture.h:299
Ptex::String::c_str
const char * c_str() const
Definition Ptexture.h:307
PTEX_NAMESPACE_BEGIN
Definition PtexSeparableKernel.cpp:42
PtexUtils::decodeDifference
void decodeDifference(void *data, size_t size, DataType dt)
Definition PtexUtils.cpp:271
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition PtexUtils.cpp:630
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:333
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:366
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition PtexUtils.cpp:422
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:406
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition PtexUtils.cpp:438
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition PtexUtils.h:167
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition PtexUtils.cpp:579
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition PtexUtils.cpp:189
ExtHeader
Definition PtexIO.h:64
ExtHeader::lmddatasize
uint64_t lmddatasize
Definition PtexIO.h:71
ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition PtexIO.h:70
ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition PtexIO.h:69
FaceDataHeader
Definition PtexIO.h:82
FaceDataHeader::encoding
Encoding encoding() const
Definition PtexIO.h:86
FaceDataHeader::blocksize
uint32_t blocksize() const
Definition PtexIO.h:85
FaceDataHeader::isLargeFace
bool isLargeFace() const
Definition PtexIO.h:94
Header
Definition PtexIO.h:44
Header::metadatamemsize
uint32_t metadatamemsize
Definition PtexIO.h:60
Header::faceinfosize
uint32_t faceinfosize
Definition PtexIO.h:54
Header::nlevels
uint16_t nlevels
Definition PtexIO.h:51
Header::nchannels
uint16_t nchannels
Definition PtexIO.h:50
Header::meshtype
uint32_t meshtype
Definition PtexIO.h:47
Header::constdatasize
uint32_t constdatasize
Definition PtexIO.h:55
Header::levelinfosize
uint32_t levelinfosize
Definition PtexIO.h:56
Header::extheadersize
uint32_t extheadersize
Definition PtexIO.h:53
Header::metadatazipsize
uint32_t metadatazipsize
Definition PtexIO.h:59
Header::datatype
uint32_t datatype
Definition PtexIO.h:48
Header::pixelSize
int pixelSize() const
Definition PtexIO.h:61
Header::alphachan
int32_t alphachan
Definition PtexIO.h:49
Header::magic
uint32_t magic
Definition PtexIO.h:45
Header::nfaces
uint32_t nfaces
Definition PtexIO.h:52
Header::leveldatasize
uint64_t leveldatasize
Definition PtexIO.h:58
Header::version
uint32_t version
Definition PtexIO.h:46
Header::hasAlpha
bool hasAlpha() const
Definition PtexIO.h:62
LevelInfo
Definition PtexIO.h:75
LevelInfo::levelheadersize
uint32_t levelheadersize
Definition PtexIO.h:77
LevelInfo::nfaces
uint32_t nfaces
Definition PtexIO.h:78
PtexReader::MetaData::Entry
Definition PtexReader.h:287
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition PtexReader.h:294
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition PtexReader.h:295
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition PtexReader.h:292
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition PtexReader.h:290
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition PtexReader.h:293
PtexReader::MetaData::Entry::data
char * data
Definition PtexReader.h:291
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition Ptexture.h:232
Ptex::Res
Pixel resolution of a given texture.
Definition Ptexture.h:159