1 | // tLayer.cpp  |
2 | //  |
3 | // A tLayer is a data container for texture pixel data. It is used only by the tTexture class to store image data. It  |
4 | // contains data that may be in a variety of hardware-ready formats, like dxt5. It is primarily used to store the  |
5 | // multiple mipmap layers of a texture. Main members are width, height, pixel format, and a function to compute data  |
6 | // size based on those three variables. It knows how to save and load itself in tChunk format.  |
7 | //  |
8 | // tLayers may have any width and height in [1, MaxLayerDimension]. If the pixel format is block-based (4x4 pixels)  |
9 | // the tLayer still allows smaller than 4 width and height. However, a whole block is still needed so the number of  |
10 | // bytes will be the block size for the particular BC format. For example, a 1x1 BC1 format layer still needs 8 bytes.  |
11 | // A 5x5 BC format layer would need 4 blocks (same as an 8x8). The tLayer does not place further constraints on width  |
12 | // and height. A higher level system, for example, may want to ensure power-of-two sizes, or multiple of 4, but that  |
13 | // shouldn't and doesn't happen here.  |
14 | //  |
15 | // Copyright (c) 2006, 2017 Tristan Grimmer.  |
16 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
17 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
18 | //  |
19 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
21 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
22 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
23 | // PERFORMANCE OF THIS SOFTWARE.  |
24 |   |
25 | #include "Image/tLayer.h"  |
26 | using namespace tImage;  |
27 |   |
28 |   |
29 | bool tLayer::IsOpaqueFormat() const  |
30 | {  |
31 | // We assume that if the layer is using a format that supports transparency that there are, in fact, transparent  |
32 | // pixels present. It won't hurt if there aren't, but it would be rendered with blending on if the material was  |
33 | // opaque and might be a bit slower.  |
34 | switch (PixelFormat)  |
35 | {  |
36 | case tPixelFormat::R8G8B8A8:  |
37 | case tPixelFormat::B8G8R8A8:  |
38 | case tPixelFormat::BC1_DXT1BA:  |
39 | case tPixelFormat::BC2_DXT3:  |
40 | case tPixelFormat::BC3_DXT5:  |
41 | case tPixelFormat::G3B5A1R5G2:  |
42 | case tPixelFormat::G4B4A4R4:  |
43 | case tPixelFormat::L8A8:  |
44 | return false;  |
45 |   |
46 | default:  |
47 | return true;  |
48 | }  |
49 |   |
50 | return true;  |
51 | }  |
52 |   |
53 |   |
54 | bool tLayer::operator==(const tLayer& src) const  |
55 | {  |
56 | if (!IsValid() || !src.IsValid())  |
57 | return false;  |
58 |   |
59 | if (PixelFormat != src.PixelFormat)  |
60 | return false;  |
61 |   |
62 | if ((Width != src.Width) || (Height != src.Height))  |
63 | return false;  |
64 |   |
65 | int dataSize = GetDataSize();  |
66 | return tStd::tMemcmp(Data, src.Data, dataSize) ? false : true;  |
67 | }  |
68 |   |
69 |   |
70 | void tLayer::Save(tChunkWriter& chunk) const  |
71 | {  |
72 | chunk.Begin(tChunkID::Image_Layer);  |
73 | {  |
74 | // This chunk must be saved first.  |
75 | chunk.Begin(tChunkID::Image_LayerProperties);  |
76 | {  |
77 | chunk.Write(PixelFormat);  |
78 | chunk.Write(Width);  |
79 | chunk.Write(Height);  |
80 | }  |
81 | chunk.End();  |
82 |   |
83 | chunk.Begin(tChunkID::Image_LayerData);  |
84 | {  |
85 | int dataSize = GetDataSize();  |
86 | chunk.Write(Data, dataSize);  |
87 | }  |
88 | chunk.End();  |
89 | }  |
90 | chunk.End();  |
91 | }  |
92 |   |
93 |   |
94 | void tLayer::Load(const tChunk& chunk, bool ownsData)  |
95 | {  |
96 | Clear();  |
97 | if (chunk.ID() != tChunkID::Image_Layer)  |
98 | return;  |
99 |   |
100 | OwnsData = ownsData;  |
101 | for (tChunk ch = chunk.First(); ch.IsValid(); ch = ch.Next())  |
102 | {  |
103 | switch (ch.ID())  |
104 | {  |
105 | // This chunk must be loaded first.  |
106 | case tChunkID::Image_LayerProperties:  |
107 | {  |
108 | ch.GetItem(PixelFormat);  |
109 | ch.GetItem(Width);  |
110 | ch.GetItem(Height);  |
111 | break;  |
112 | }  |
113 |   |
114 | case tChunkID::Image_LayerData:  |
115 | {  |
116 | int dataSize = GetDataSize();  |
117 | if (dataSize <= 0)  |
118 | return;  |
119 |   |
120 | tAssert(!Data);  |
121 | if (OwnsData)  |
122 | {  |
123 | Data = new uint8[dataSize];  |
124 | tStd::tMemcpy(Data, ch.Data(), dataSize);  |
125 | }  |
126 | else  |
127 | {  |
128 | Data = (uint8*)ch.Data();  |
129 | }  |
130 | break;  |
131 | }  |
132 | }  |
133 | }  |
134 | }  |
135 | |