1// tLayer.h 
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#pragma once 
26#include <Foundation/tList.h> 
27#include <System/tChunk.h> 
28#include <Image/tPixelFormat.h> 
29namespace tImage 
30
31 
32 
33class tLayer : public tLink<tLayer
34
35public
36 tLayer() : PixelFormat(tPixelFormat::Invalid), Width(0), Height(0), Data(nullptr), OwnsData(true) { } 
37 
38 // Constructs the layer from the chunk. Normally it copies the layer data from the chunk. However, if ownData is 
39 // false no mem-copy is performed and the layer just points into the chunk data. In this case it is vital that the 
40 // chunk object exists for the entire lifespan of the layer. 
41 tLayer(const tChunk& chunk, bool ownsData = true) : PixelFormat(tPixelFormat::Invalid), Width(0), Height(0), Data(nullptr), OwnsData(ownsData) { Load(chunk, ownsData); } 
42 
43 // Constructs a layer having the supplied width, height, and number of bytes. If steal memory is true, the data 
44 // array is passed off to this class and it will manage the array deleting it when necessary. If steal is false, 
45 // the data gets mem-copied into this object. 
46 tLayer(tPixelFormat, int width, int height, uint8* data, bool steal = false); 
47 
48 tLayer(const tLayer&); 
49 virtual ~tLayer() { Clear(); } 
50 
51 bool IsValid() const { return Data ? true : false; } 
52 
53 // Returns the size of the data in bytes. For BC formats the data size will be a multiple of the block size. For 
54 // example, a 1x1 BC1 format layer still needs 8 bytes. A 5x5 BC1 format layer would need a whole 4 blocks (same as 
55 // an 8x8) and would yield 32 bytes. 
56 int GetDataSize() const
57 
58 void Save(tChunkWriter&) const
59 
60 // Loads the layer from a chunk. Any previous layer data gets destroyed. The bool ownData works the same as with 
61 // the constructor. 
62 void Load(const tChunk&, bool ownData); 
63 
64 // Frees internal layer data and makes the layer invalid. 
65 void Clear() { PixelFormat = tPixelFormat::Invalid; Width = Height = 0; if (OwnsData) delete[] Data; Data = nullptr; OwnsData = true; } 
66 
67 // This just checks the pixel format to see if it supports alpha. It does NOT check the data. 
68 bool IsOpaqueFormat() const
69 
70 // An invalid layer is never considered equal to another layer even if the other layer is also invalid. Whether the 
71 // layer owns the data is considered irrelevant for equivalency purposes. 
72 bool operator==(const tLayer&) const
73 bool operator!=(const tLayer& src) const { return !(*this == src); } 
74 
75 tPixelFormat PixelFormat
76 int Width, Height
77 uint8* Data
78 bool OwnsData
79 
80 // Most hardware can handle up to a 4096 x 4096 texture. 
81 const static int MaxLayerDimension = 4096
82 const static int MinLayerDimension = 1
83}; 
84 
85 
86// Implementation below this line. 
87 
88 
89inline tLayer::tLayer(tPixelFormat format, int width, int height, uint8* data, bool steal) : 
90 PixelFormat(format), 
91 Width(width), 
92 Height(height), 
93 Data(nullptr), 
94 OwnsData(true
95
96 if (!width || !height || !data
97 return
98 
99 if (steal
100
101 Data = data
102
103 else 
104
105 int dataSize = GetDataSize(); 
106 Data = new uint8[dataSize]; 
107 tStd::tMemcpy(Data, data, dataSize); 
108
109
110 
111 
112inline tLayer::tLayer(const tLayer& src) : 
113 PixelFormat(src.PixelFormat), 
114 Width(src.Width), 
115 Height(src.Height), 
116 OwnsData(src.OwnsData
117
118 if (OwnsData
119
120 int dataSize = src.GetDataSize(); 
121 Data = new uint8[dataSize]; 
122 tStd::tMemcpy(Data, src.Data, dataSize); 
123
124 else 
125
126 Data = src.Data
127
128
129 
130 
131inline int tLayer::GetDataSize() const 
132
133 if (!Width || !Height || (PixelFormat == tPixelFormat::Invalid)) 
134 return 0
135 
136 int numBytes = 0
137 if (tIsBlockFormat(PixelFormat)) 
138
139 int widthNumBlocks = (Width + ((Width%4) ? 4-(Width%4) : 0)) >> 2
140 int heightNumBlocks = (Height + ((Height%4) ? 4-(Height%4) : 0)) >> 2
141 int numBlocks = widthNumBlocks * heightNumBlocks
142 numBytes = numBlocks * tGetBytesPer4x4PixelBlock(PixelFormat); 
143
144 else 
145
146 numBytes = Width * Height * (tGetBitsPerPixel(PixelFormat) >> 3); 
147
148 
149 return numBytes
150
151 
152 
153
154