1 /*
2 
3 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
4 	and the "Aleph One" developers.
5 
6 	This program is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 3 of the License, or
9 	(at your option) any later version.
10 
11 	This program is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	This license is contained in the file "COPYING",
17 	which is included with this source code; it is available online at
18 	http://www.gnu.org/licenses/gpl.html
19 
20 	OpenGL Texture Manager,
21 	by Loren Petrich,
22 	March 12, 2000
23 
24 	This contains functions for handling the texture management for OpenGL.
25 
26 Nov 18, 2000 (Loren Petrich):
27 	Added support for landscape vertical repeats
28 
29 May 3, 2003 (Br'fin (Jeremy Parsons))
30 	Added LowLevelShape workaround for passing LowLevelShape info of sprites
31 	instead of abusing/overflowing shape_descriptors
32 */
33 
34 #ifndef _OGL_TEXTURES
35 #define _OGL_TEXTURES
36 
37 #include "OGL_Headers.h"
38 #include "OGL_Subst_Texture_Def.h"
39 #include "scottish_textures.h"
40 
41 // Initialize the texture accounting
42 void OGL_StartTextures();
43 
44 // Done with the texture accounting
45 void OGL_StopTextures();
46 
47 // Call this after every frame for housekeeping stuff
48 void OGL_FrameTickTextures();
49 
50 // State of an individual texture set:
51 struct TextureState
52 {
53 	// Which member textures?
54 	enum
55 	{
56 		Normal,		// Used for all normally-shaded and shadeless textures
57 		Glowing,	// Used for self-luminous textures
58 		Bump,	    // Bump map for textures
59 		NUMBER_OF_TEXTURES
60 	};
61 	GLuint IDs[NUMBER_OF_TEXTURES];		// Texture ID's
62 	bool IsUsed;						// Is the texture set being used?
63 	bool IsGlowing;						// Does the texture have a glow map?
64 	bool IsBumped;						// Does the texture have a bump map?
65 	bool TexGened[NUMBER_OF_TEXTURES];	// Which ID's have had their textures generated?
66 	int IDUsage[NUMBER_OF_TEXTURES];	// Which ID's are being used?  Reset every frame.
67 	int unusedFrames;					// How many frames have passed since we were last used.
68 	short TextureType;
69 
70     GLdouble U_Scale;
71     GLdouble V_Scale;
72     GLdouble U_Offset;
73     GLdouble V_Offset;
74 
TextureStateTextureState75 	TextureState() {IsUsed = false; Reset(); TextureType = NONE; U_Scale = V_Scale = 1; U_Offset = V_Offset = 0;}
~TextureStateTextureState76 	~TextureState() {Reset();}
77 
78 	// Allocate some textures and indicate whether an allocation had happened.
79 	bool Allocate(short txType);
80 
81 	// These indicate that some texture
82 	bool Use(int Which);
UseNormalTextureState83 	bool UseNormal() {return Use(Normal);}
UseGlowingTextureState84 	bool UseGlowing() {return Use(Glowing);}
UseBumpTextureState85 	bool UseBump() {return Use(Bump);}
86 
87 	void FrameTick();
88 
89 	// Reset the texture to unused and force a reload if necessary
90 	void Reset();
91 };
92 
93 
94 /*
95 	This is the collected texture states per collection bitmap;
96 	it contains both texture-mapping info and the state for each color-table value.
97 
98 	The GLdouble stuff is for setting up offsets of the texture coordinates, using:
99 	Texture Coordinate = (offset) + (scale) * (clip position)
100 	where (scale) = (sprite size) / (texture size)
101 	and (clip position) = ((clip screen position) - (left screen position)) /
102 		((right screen position) - (left screen position))
103 */
104 struct CollBitmapTextureState
105 {
106 	TextureState CTStates[NUMBER_OF_OPENGL_BITMAP_SETS];
107 
108 	// Sensible default
CollBitmapTextureStateCollBitmapTextureState109 	CollBitmapTextureState() {}
110 };
111 
112 
113 // Modify color-table index if necessary;
114 // makes it the infravision or silhouette one if necessary
115 short ModifyCLUT(short TransferMode, short CLUT);
116 
117 
118 // Intended to be the no-texture default argument
119 const int BadTextureType = 32767;
120 
121 /*
122 	Texture-manager object: contains all the handling of textures;
123 	it finds their setting up, their dimensions, and so forth.
124 
125 	It is designed to be created and destroyed
126 	once each rendering go-around with each texture.
127 */
128 
129 class TextureManager
130 {
131 	// Width: along scanlines; height; from scanline to scanline
132 	// Wall textures and sprites are horizontal-vertical flipped
133 
134 	// Various texture ID's:
135 	short Collection;
136 	short CTable;
137 	short Frame;
138 	short Bitmap;
139 
140 	// Info transmitted from the setting-up phase
141 	bool IsGlowing;
142 
143 	// Width and height and whether to do RLE
144 	// These are, in order, for the original texture, for the OpenGL texture,
145 	// and the offsets in the original in the OpenGL texture.
146 	// Also, the loaded-texture dimensions, in case the textures get shrunk.
147 	short BaseTxtrWidth, BaseTxtrHeight;
148 	short TxtrWidth, TxtrHeight;
149 	short WidthOffset, HeightOffset;
150 	short LoadedWidth, LoadedHeight;
151 
152 	// Color table: need it for going from indexed to true color;
153 	// both normal and glow-mapped versions are needed
154 	uint32 NormalColorTable[MAXIMUM_SHADING_TABLE_INDEXES];
155 	uint32 GlowColorTable[MAXIMUM_SHADING_TABLE_INDEXES];
156 
157 	// Texture buffers for OpenGL
158 	uint32 *NormalBuffer, *GlowBuffer;
159 
160 	// New texture buffers
161 	ImageDescriptorManager NormalImage, GlowImage, OffsetImage;
162 
163 	// Pointer to the appropriate texture-state object
164 	TextureState *TxtrStatePtr;
165 
166 	// Pointer to texture-options object
167 	OGL_TextureOptions *TxtrOptsPtr;
168 
169 	// Private methods
170 
171 	// This one tries to load substitute textures into NormalBuffer and GlowBuffer;
172 	// it returns whether such textures were loaded.
173 	bool LoadSubstituteTexture();
174 
175 	// This one finds the width, height, etc. of a texture type;
176 	// it returns "false" if some texture's dimensions do not fit.
177 	bool SetupTextureGeometry();
178 
179 	// This one finds the color tables
180 	void FindColorTables();
181 
182 	// premultiplies color table alpha
183 	void PremultiplyColorTables();
184 
185 	// This one allocates an OpenGL texture buffer and uses a color table
186 	uint32 *GetOGLTexture(uint32 *ColorTable);
187 
188 	// This one creates a fake landscape
189 	uint32 *GetFakeLandscape();
190 
191 	// This is for shrinking a texture
192 	uint32 *Shrink(uint32 *Buffer);
193 
194 	// This is for placing a texture in OpenGL
195 	void PlaceTexture(const ImageDescriptor *, bool normal_map = false);
196 
197 public:
198 
199 	// Inputs: get off of texture object passed to scottish_textures.
200 	shape_descriptor ShapeDesc;
201 	uint16 LowLevelShape;
202 	bitmap_definition *Texture;
203 	void *ShadingTables;
204 	short TransferMode;
205 	short TransferData;
206 	bool IsShadeless;
207 	short TextureType;
208 	bool LandscapeVertRepeat;
209 
210 	bool FastPath;
211 
212 	// The width of a landscape texture will be 2^(-Landscape_AspRatExp) * (the height)
213 	short Landscape_AspRatExp;
214 
215 	// Sets up all the texture stuff:
216 	bool Setup();
217 
218 	// Results:
219 
220 	// Various texture ID's:
GetCollection()221 	short GetCollection() {return Collection;}
GetCTable()222 	short GetCTable() {return CTable;}
GetFrame()223 	short GetFrame() {return Frame;}
GetBitmap()224 	short GetBitmap() {return Bitmap;}
225 
226 	// Info transmitted from the setting-up phase:
227 	// texture type, whether it is glowmapped,
228 	// and whether the textures are blended rather than all-or-nothing crisp-edged
GetTextureType()229 	int GetTextureType() {return TextureType;}
IsGlowMapped()230 	bool IsGlowMapped() {return IsGlowing;}
IsBlended()231 	bool IsBlended() {return (TxtrOptsPtr->OpacityType != OGL_OpacType_Crisp);}
VoidVisible()232 	bool VoidVisible() {return (TxtrOptsPtr->VoidVisible);}
NormalBlend()233 	short NormalBlend() {return (TxtrOptsPtr->NormalBlend) + ((NormalImage.get() && NormalImage.get()->IsPremultiplied() && TxtrOptsPtr->NormalBlend < OGL_FIRST_PREMULT_ALPHA) ? OGL_FIRST_PREMULT_ALPHA : 0); }
GlowBlend()234 	short GlowBlend() {return (TxtrOptsPtr->GlowBlend) + ((GlowImage.get() && GlowImage.get()->IsPremultiplied() && TxtrOptsPtr->GlowBlend < OGL_FIRST_PREMULT_ALPHA) ? OGL_FIRST_PREMULT_ALPHA : 0); }
MinGlowIntensity()235 	float MinGlowIntensity() {return (TxtrOptsPtr->MinGlowIntensity);}
BloomScale()236 	float BloomScale() {return (TxtrOptsPtr->BloomScale);}
BloomShift()237 	float BloomShift() {return (TxtrOptsPtr->BloomShift);}
GlowBloomScale()238 	float GlowBloomScale() {return (TxtrOptsPtr->GlowBloomScale);}
GlowBloomShift()239 	float GlowBloomShift() {return (TxtrOptsPtr->GlowBloomShift);}
LandscapeBloom()240 	float LandscapeBloom() {return (TxtrOptsPtr->LandscapeBloom);}
241 
242 	// Scaling and offset of the current texture;
243 	// important for sprites, which will be padded to make them OpenGL-friendly.
244 	GLdouble U_Scale, V_Scale, U_Offset, V_Offset;
245 
246 	// What to render:
247 
248 	// Always call this one and call it first; safe to allocate texture ID's in it
249 	void RenderNormal();
250 	// Call this one after RenderNormal()
251 	void RenderGlowing();
252 	void RenderBump();
253 
254 	void SetupTextureMatrix();
255 	void RestoreTextureMatrix();
256 
257 	TextureManager();
258 	~TextureManager();
259 };
260 
261 
262 // Color-transformation macros:
263 
264 // Five-to-eight translation:
265 // takes a 5-bit color value and expands it to 8 bytes
FiveToEight(byte x)266 inline byte FiveToEight(byte x) {return (x << 3) | ((x >> 2) & 0x07);}
267 
268 // 16-bit-to-32-bit with opacity = 1;
269 // ARGB 1555 to RGBA 8888
Convert_16to32(uint16 InPxl)270 inline GLuint Convert_16to32(uint16 InPxl)
271 {
272 	if (PlatformIsLittleEndian()) {
273 		// perfect target for constexpr-if in C++17
274 		// Alpha preset
275 		GLuint OutPxl = 0xff000000;
276 		GLuint Chan;
277 		// Red
278 		Chan = FiveToEight(InPxl >> 10);
279 		OutPxl |= Chan;
280 		// Green
281 		Chan = FiveToEight(InPxl >> 5);
282 		OutPxl |= Chan << 8;
283 		// Blue
284 		Chan = FiveToEight(InPxl & 0x1F);
285 		OutPxl |= Chan << 16;
286 		return OutPxl;
287 	} else {
288 		// Alpha preset
289 		GLuint OutPxl = 0x000000ff;
290 		GLuint Chan;
291 		// Red
292 		Chan = FiveToEight(InPxl >> 10);
293 		OutPxl |= Chan << 24;
294 		// Green
295 		Chan = FiveToEight(InPxl >> 5);
296 		OutPxl |= Chan << 16;
297 		// Blue
298 		Chan = FiveToEight(InPxl);
299 		OutPxl |= Chan << 8;
300 		return OutPxl;
301 	}
302 
303 }
304 
305 
306 // Make floating-point colors
MakeFloatColor(RGBColor & InColor,GLfloat * OutColor)307 inline void MakeFloatColor(RGBColor& InColor, GLfloat *OutColor)
308 {
309 	OutColor[0] = InColor.red/65535.0F;
310 	OutColor[1] = InColor.green/65535.0F;
311 	OutColor[2] = InColor.blue/65535.0F;
312 }
313 
MakeFloatColor(rgb_color & InColor,GLfloat * OutColor)314 inline void MakeFloatColor(rgb_color& InColor, GLfloat *OutColor)
315 {
316 	OutColor[0] = InColor.red/65535.0F;
317 	OutColor[1] = InColor.green/65535.0F;
318 	OutColor[2] = InColor.blue/65535.0F;
319 }
320 
321 /*
322 // Stuff for doing 16->32 pixel-format conversion, 1555 ARGB to 8888 RGBA
323 // The table is created only when necessary, and retained as long as it is necessary
324 extern GLuint *ConversionTable_16to32;
325 
326 extern void MakeConversion_16to32(int BitDepth);
327 */
328 
329 void LoadModelSkin(ImageDescriptor& Image, short Collection, short CLUT);
330 
331 void SetPixelOpacities(OGL_TextureOptions& Options, ImageDescriptorManager &imageManager);
332 
333 // Does this for a set of several pixel values or color-table values;
334 // the pixels are assumed to be in OpenGL-friendly byte-by-byte RGBA format.
335 void SetPixelOpacitiesRGBA(OGL_TextureOptions& Options, int NumPixels, uint32 *Pixels);
336 
337 // Infravision (I'm blue, are you?)
338 bool& IsInfravisionActive();
339 
340 // Sets the infravision tinting color for a shapes collection, and whether to use such tinting;
341 // the color values are from 0 to 1.
342 bool SetInfravisionTint(short Collection, bool IsTinted, float Red, float Green, float Blue);
343 
344 void FindInfravisionVersion(short Collection, ImageDescriptorManager &imageManager);
345 
346 // Finds the infravision version of a color;
347 // it makes no change if infravision is inactive.
348 void FindInfravisionVersionRGBA(short Collection, GLfloat *Color);
349 
350 // Mass-production version of above; suitable for textures
351 void FindInfravisionVersionRGBA(short Collection, int NumPixels, uint32 *Pixels);
352 
353 void FindSilhouetteVersion(ImageDescriptorManager &imageManager);
354 
355 struct OGL_TexturesStats {
356 	int inUse;
357 	int binds, totalBind, minBind, maxBind;
358 	int longNormalSetups, longGlowSetups, longBumpSetups;
359 	int totalAge;
360 };
361 
362 extern OGL_TexturesStats gGLTxStats;
363 
364 #endif
365