| 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 | |