1
2
3 #include "toonz/textureutils.h"
4
5 // TnzLib includes
6 #include "toonz/txshleveltypes.h"
7 #include "toonz/txshsimplelevel.h"
8 #include "toonz/txshchildlevel.h"
9 #include "toonz/txsheet.h"
10 #include "toonz/tstageobjecttree.h"
11 #include "toonz/txshcell.h"
12 #include "toonz/tstageobject.h"
13 #include "toonz/stage.h"
14 #include "toonz/toonzscene.h"
15 #include "toonz/imagemanager.h"
16 #include "imagebuilders.h"
17
18 // TnzCore includes
19 #include "tpalette.h"
20 #include "tconvert.h"
21 #include "ttoonzimage.h"
22 #include "trop.h"
23 #include "tropcm.h"
24 #include "tgl.h"
25
26 //********************************************************************************************
27 // TXshSimpleLevel Texture Utilities locals
28 //********************************************************************************************
29
30 namespace {
31
convert32(const TImageP & img)32 TRasterImageP convert32(const TImageP &img) {
33 struct locals {
34 static TRasterImageP depremultiplied(const TRasterImageP &ri) {
35 assert(ri->getRaster());
36
37 TRop::depremultiply(ri->getRaster());
38 return ri;
39 }
40 }; // locals
41
42 if (TRasterImageP ri = img) {
43 TRasterP ras(ri->getRaster());
44
45 TRaster32P ras32;
46 {
47 if (TRaster32P(ras))
48 ras32 = ras->clone();
49 else {
50 ras32 = TRaster32P(ras->getSize());
51 TRop::convert(ras32, ras);
52 }
53 }
54
55 TPointD dpi;
56 ri->getDpi(dpi.x, dpi.y);
57
58 TRasterImageP ri32(ras32);
59 ri32->setDpi(dpi.x, dpi.y);
60 ri32->setSubsampling(ri->getSubsampling());
61 ri32->setOffset(ri->getOffset());
62
63 return locals::depremultiplied(ri32);
64 }
65
66 if (TToonzImageP ti = img) {
67 TRasterCM32P rasCM32(ti->getRaster());
68
69 TRaster32P ras32(rasCM32->getSize());
70 TRop::convert(ras32, rasCM32, ti->getPalette());
71
72 TPointD dpi;
73 ti->getDpi(dpi.x, dpi.y);
74
75 TRasterImageP ri32(ras32);
76 ri32->setDpi(dpi.x, dpi.y);
77 ri32->setSubsampling(ti->getSubsampling());
78 ri32->setOffset(ti->getOffset());
79
80 return locals::depremultiplied(ri32);
81 }
82
83 return TRasterImageP();
84 }
85
86 //-----------------------------------------------------------------------------
87
getTexture(const TXshSimpleLevel * sl,const TFrameId & fid,int subsampling)88 TRasterImageP getTexture(const TXshSimpleLevel *sl, const TFrameId &fid,
89 int subsampling) {
90 if (sl->getType() != PLI_XSHLEVEL) {
91 TImageP texImg =
92 sl->getFrame(fid, ImageManager::dontPutInCache, subsampling);
93 return convert32(texImg);
94 }
95
96 // Vector case
97 std::string id = sl->getImageId(fid) + "_rasterized";
98
99 ImageLoader::BuildExtData extData(sl, fid);
100 TRasterImageP ri(ImageManager::instance()->getImage(
101 id, ImageManager::dontPutInCache, &extData));
102
103 return convert32(ri);
104 }
105
106 } // namespace
107
108 //********************************************************************************************
109 // TXshSimpleLevel Texture Utilities implementation
110 //********************************************************************************************
111
getTextureData(const TXshSimpleLevel * sl,const TFrameId & fid,int subsampling)112 DrawableTextureDataP texture_utils::getTextureData(const TXshSimpleLevel *sl,
113 const TFrameId &fid,
114 int subsampling) {
115 const std::string &texId = sl->getImageId(fid);
116
117 // Now, we must associate a texture
118 DrawableTextureDataP data(
119 TTexturesStorage::instance()->getTextureData(texId));
120 if (data) return data;
121
122 // There was no associated texture. We must bind the texture and repeat
123
124 // First, retrieve the image to be used as texture
125 TRasterImageP ri(::getTexture(sl, fid, subsampling));
126 if (!ri) return DrawableTextureDataP();
127
128 TRaster32P ras(ri->getRaster());
129 assert(ras);
130
131 TRectD geom(0, 0, ras->getLx(), ras->getLy());
132 geom = TScale(ri->getSubsampling()) *
133 TTranslation(convert(ri->getOffset()) - ras->getCenterD()) * geom;
134
135 return TTexturesStorage::instance()->loadTexture(texId, ras, geom);
136 }
137
138 //-----------------------------------------------------------------------------
139
invalidateTexture(const TXshSimpleLevel * sl,const TFrameId & fid)140 void texture_utils::invalidateTexture(const TXshSimpleLevel *sl,
141 const TFrameId &fid) {
142 const std::string &texId = sl->getImageId(fid);
143 TTexturesStorage::instance()->unloadTexture(texId);
144 }
145
146 //-----------------------------------------------------------------------------
147
invalidateTextures(const TXshSimpleLevel * sl)148 void texture_utils::invalidateTextures(const TXshSimpleLevel *sl) {
149 int f, fCount = sl->getFrameCount();
150
151 for (f = 0; f != fCount; ++f) invalidateTexture(sl, sl->getFrameId(f));
152 }
153
154 //********************************************************************************************
155 // TXsheet Texture Utilities locals
156 //********************************************************************************************
157
158 namespace {
159
getImageId(const TXsheet * xsh,int frame)160 std::string getImageId(const TXsheet *xsh, int frame) {
161 return "X" + std::to_string(xsh->id()) + "_" + std::to_string(frame);
162 }
163
164 } // namespace
165
166 //********************************************************************************************
167 // TXsheet Texture Utilities implementation
168 //********************************************************************************************
169
getTextureData(const TXsheet * xsh,int frame)170 DrawableTextureDataP texture_utils::getTextureData(const TXsheet *xsh,
171 int frame) {
172 // Check if an xsheet texture already exists
173 const std::string &texId = ::getImageId(xsh, frame);
174
175 DrawableTextureDataP data(
176 TTexturesStorage::instance()->getTextureData(texId));
177 if (data) return data;
178
179 // No available texture - we must build and load it
180 TRaster32P tex(
181 1024,
182 1024); // Fixed texture size. It's the same that currently happens with
183 // vector images' textures - and justified since this is camstand
184 // mode, and besides we want to make sure that textures are limited.
185
186 // Retrieve the sub-xsheet bbox (world coordinates of the sub-xsheet)
187 TRectD bbox(xsh->getBBox(frame));
188
189 // Since xsh represents a sub-xsheet, its camera affine must be applied
190 const TAffine &cameraAff =
191 xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), frame);
192 bbox = (cameraAff.inv() * bbox).enlarge(1.0);
193
194 // Render the xsheet on the specified bbox
195 #ifdef MACOSX
196 xsh->getScene()->renderFrame(tex, frame, xsh, bbox, TAffine());
197 #else
198 // The call below will change context (I know, it's a shame :( )
199 TGlContext currentContext = tglGetCurrentContext();
200 {
201 tglDoneCurrent(currentContext);
202 xsh->getScene()->renderFrame(tex, frame, xsh, bbox, TAffine());
203 tglMakeCurrent(currentContext);
204 }
205 #endif
206
207 TRop::depremultiply(tex); // Stored textures are rendered nonpremultiplied
208
209 // Store the texture for future retrieval
210 return TTexturesStorage::instance()->loadTexture(texId, tex, bbox);
211 }
212
213 //-----------------------------------------------------------------------------
214
invalidateTexture(const TXsheet * xsh,int frame)215 void texture_utils::invalidateTexture(const TXsheet *xsh, int frame) {
216 const std::string &texId = ::getImageId(xsh, frame);
217 TTexturesStorage::instance()->unloadTexture(texId);
218 }
219
220 //-----------------------------------------------------------------------------
221
invalidateTextures(const TXsheet * xsh)222 void texture_utils::invalidateTextures(const TXsheet *xsh) {
223 int f, fCount = xsh->getFrameCount();
224 for (f = 0; f != fCount; ++f) invalidateTexture(xsh, f);
225 }
226