1 // Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #include "IrrCompileConfig.h"
6 #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
7 
8 #include "SoftwareDriver2_compile_config.h"
9 #include "SoftwareDriver2_helper.h"
10 #include "CSoftwareTexture2.h"
11 #include "os.h"
12 
13 namespace irr
14 {
15 namespace video
16 {
17 
18 //! constructor
CSoftwareTexture2(IImage * image,const io::path & name,u32 flags,void * mipmapData)19 CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name,
20 		u32 flags, void* mipmapData)
21 		: ITexture(name), MipMapLOD(0), Flags ( flags ), OriginalFormat(video::ECF_UNKNOWN)
22 {
23 	#ifdef _DEBUG
24 	setDebugName("CSoftwareTexture2");
25 	#endif
26 
27 	#ifndef SOFTWARE_DRIVER_2_MIPMAPPING
28 		Flags &= ~GEN_MIPMAP;
29 	#endif
30 
31 	memset32 ( MipMap, 0, sizeof ( MipMap ) );
32 
33 	if (image)
34 	{
35 		OrigSize = image->getDimension();
36 		OriginalFormat = image->getColorFormat();
37 
38 		core::setbit_cond(Flags,
39 				image->getColorFormat () == video::ECF_A8R8G8B8 ||
40 				image->getColorFormat () == video::ECF_A1R5G5B5,
41 				HAS_ALPHA);
42 
43 		core::dimension2d<u32> optSize(
44 				OrigSize.getOptimalSize( 0 != ( Flags & NP2_SIZE ),
45 				false, false,
46 				( Flags & NP2_SIZE ) ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 0)
47 			);
48 
49 		if ( OrigSize == optSize )
50 		{
51 			MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension());
52 			image->copyTo(MipMap[0]);
53 		}
54 		else
55 		{
56 			char buf[256];
57 			core::stringw showName ( name );
58 			snprintf ( buf, 256, "Burningvideo: Warning Texture %ls reformat %dx%d -> %dx%d,%d",
59 							showName.c_str(),
60 							OrigSize.Width, OrigSize.Height, optSize.Width, optSize.Height,
61 							BURNINGSHADER_COLOR_FORMAT
62 						);
63 
64 			OrigSize = optSize;
65 			os::Printer::log ( buf, ELL_WARNING );
66 			MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize);
67 			image->copyToScalingBoxFilter ( MipMap[0],0, false );
68 		}
69 
70 		OrigImageDataSizeInPixels = (f32) 0.3f * MipMap[0]->getImageDataSizeInPixels();
71 	}
72 
73 	regenerateMipMapLevels(mipmapData);
74 }
75 
76 
77 //! destructor
~CSoftwareTexture2()78 CSoftwareTexture2::~CSoftwareTexture2()
79 {
80 	for ( s32 i = 0; i!= SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i )
81 	{
82 		if ( MipMap[i] )
83 			MipMap[i]->drop();
84 	}
85 }
86 
87 
88 //! Regenerates the mip map levels of the texture. Useful after locking and
89 //! modifying the texture
regenerateMipMapLevels(void * mipmapData)90 void CSoftwareTexture2::regenerateMipMapLevels(void* mipmapData)
91 {
92 	if ( !hasMipMaps () )
93 		return;
94 
95 	s32 i;
96 
97 	// release
98 	for ( i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i )
99 	{
100 		if ( MipMap[i] )
101 			MipMap[i]->drop();
102 	}
103 
104 	core::dimension2d<u32> newSize;
105 	core::dimension2d<u32> origSize=OrigSize;
106 
107 	for (i=1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i)
108 	{
109 		newSize = MipMap[i-1]->getDimension();
110 		newSize.Width = core::s32_max ( 1, newSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE );
111 		newSize.Height = core::s32_max ( 1, newSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE );
112 		origSize.Width = core::s32_max(1, origSize.Width >> 1);
113 		origSize.Height = core::s32_max(1, origSize.Height >> 1);
114 
115 		if (mipmapData)
116 		{
117 			if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT)
118 			{
119 				IImage* tmpImage = new CImage(OriginalFormat, origSize, mipmapData, true, false);
120 				MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize);
121 				if (origSize==newSize)
122 					tmpImage->copyTo(MipMap[i]);
123 				else
124 					tmpImage->copyToScalingBoxFilter(MipMap[i]);
125 				tmpImage->drop();
126 			}
127 			else
128 			{
129 				if (origSize==newSize)
130 					MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mipmapData, false);
131 				else
132 				{
133 					MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize);
134 					IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mipmapData, true, false);
135 					tmpImage->copyToScalingBoxFilter(MipMap[i]);
136 					tmpImage->drop();
137 				}
138 			}
139 			mipmapData = (u8*)mipmapData+origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat)/8;
140 		}
141 		else
142 		{
143 			MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize);
144 
145 			//static u32 color[] = { 0, 0xFFFF0000, 0xFF00FF00,0xFF0000FF,0xFFFFFF00,0xFFFF00FF,0xFF00FFFF,0xFF0F0F0F };
146 			MipMap[i]->fill ( 0 );
147 			MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false );
148 		}
149 	}
150 }
151 
152 
153 } // end namespace video
154 } // end namespace irr
155 
156 #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
157