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