1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 */
19
20 #include "TextureManager.h"
21
22
23 //////////////////////////////////////////
24 // Constructors / Deconstructors
25
26 // Probably shouldn't need more than 4096 * 4096
27
CTexture(uint32_t dwWidth,uint32_t dwHeight,TextureUsage usage)28 CTexture::CTexture(uint32_t dwWidth, uint32_t dwHeight, TextureUsage usage) :
29 m_dwWidth(dwWidth),
30 m_dwHeight(dwHeight),
31 m_dwCreatedTextureWidth(dwWidth),
32 m_dwCreatedTextureHeight(dwHeight),
33 m_fXScale(1.0f),
34 m_fYScale(1.0f),
35 m_bScaledS(false),
36 m_bScaledT(false),
37 m_bClampedS(false),
38 m_bClampedT(false),
39 m_bIsEnhancedTexture(false),
40 m_Usage(usage),
41 m_pTexture(NULL),
42 m_dwTextureFmt(TEXTURE_FMT_A8R8G8B8)
43 {
44 // fix me, do something here
45 }
46
47
~CTexture(void)48 CTexture::~CTexture(void)
49 {
50 }
51
GetSurfaceFormat(void)52 TextureFmt CTexture::GetSurfaceFormat(void)
53 {
54 if (m_pTexture == NULL)
55 return TEXTURE_FMT_UNKNOWN;
56 return m_dwTextureFmt;
57 }
58
GetPixelSize()59 uint32_t CTexture::GetPixelSize()
60 {
61 if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 )
62 return 4;
63 return 2;
64 }
65
66
67 // There are reasons to create this function. D3D and OGL will only create surface of width and height
68 // as 2's pow, for example, N64's 20x14 image, D3D and OGL will create a 32x16 surface.
69 // When we using such a surface as D3D texture, and the U and V address is for the D3D and OGL surface
70 // width and height. It is still OK if the U and V addr value is less than the real image within
71 // the D3D surface. But we will have problems if the U and V addr value is larger than it, or even
72 // large then 1.0.
73 // In such a case, we need to scale the image to the D3D surface dimension, to ease the U/V addr
74 // limition
ScaleImageToSurface(bool scaleS,bool scaleT)75 void CTexture::ScaleImageToSurface(bool scaleS, bool scaleT)
76 {
77 uint8_t g_ucTempBuffer[1024*1024*4];
78
79 if( scaleS==false && scaleT==false)
80 return;
81
82 // If the image is not scaled, call this function to scale the real image to
83 // the D3D given dimension
84
85 uint32_t width = scaleS ? m_dwWidth : m_dwCreatedTextureWidth;
86 uint32_t height = scaleT ? m_dwHeight : m_dwCreatedTextureHeight;
87
88 uint32_t xDst, yDst;
89 uint32_t xSrc, ySrc;
90
91 DrawInfo di;
92
93 if (!StartUpdate(&di))
94 return;
95
96 int pixSize = GetPixelSize();
97
98 // Copy across from the temp buffer to the surface
99 switch (pixSize)
100 {
101 case 4:
102 {
103 memcpy((uint8_t*)g_ucTempBuffer, (uint8_t*)(di.lpSurface), m_dwHeight*m_dwCreatedTextureWidth*4);
104
105 uint32_t * pDst;
106 uint32_t * pSrc;
107
108 for (yDst = 0; yDst < m_dwCreatedTextureHeight; yDst++)
109 {
110 // ySrc ranges from 0..m_dwHeight
111 // I'd rather do this but sometimes very narrow (i.e. 1 pixel)
112 // surfaces are created which results in /0...
113 //ySrc = (yDst * (m_dwHeight-1)) / (d3dTextureHeight-1);
114 ySrc = (uint32_t)((yDst * height) / m_dwCreatedTextureHeight+0.49f);
115
116 pSrc = (uint32_t*)((uint8_t*)g_ucTempBuffer + (ySrc * m_dwCreatedTextureWidth * 4));
117 pDst = (uint32_t*)((uint8_t*)di.lpSurface + (yDst * di.lPitch));
118
119 for (xDst = 0; xDst < m_dwCreatedTextureWidth; xDst++)
120 {
121 xSrc = (uint32_t)((xDst * width) / m_dwCreatedTextureWidth+0.49f);
122 pDst[xDst] = pSrc[xSrc];
123 }
124 }
125 }
126
127 break;
128 case 2:
129 {
130 memcpy((uint8_t*)g_ucTempBuffer, (uint8_t*)(di.lpSurface), m_dwHeight*m_dwCreatedTextureWidth*2);
131
132 uint16_t * pDst;
133 uint16_t * pSrc;
134
135 for (yDst = 0; yDst < m_dwCreatedTextureHeight; yDst++)
136 {
137 // ySrc ranges from 0..m_dwHeight
138 ySrc = (yDst * height) / m_dwCreatedTextureHeight;
139
140 pSrc = (uint16_t*)((uint8_t*)g_ucTempBuffer + (ySrc * m_dwCreatedTextureWidth * 2));
141 pDst = (uint16_t*)((uint8_t*)di.lpSurface + (yDst * di.lPitch));
142
143 for (xDst = 0; xDst < m_dwCreatedTextureWidth; xDst++)
144 {
145 xSrc = (xDst * width) / m_dwCreatedTextureWidth;
146 pDst[xDst] = pSrc[xSrc];
147 }
148 }
149 }
150 break;
151 }
152
153 EndUpdate(&di);
154
155 if( scaleS ) m_bScaledS = true;
156 if( scaleT ) m_bScaledT = true;
157 }
158
ClampImageToSurfaceS()159 void CTexture::ClampImageToSurfaceS()
160 {
161 if( !m_bClampedS && m_dwWidth < m_dwCreatedTextureWidth )
162 {
163 DrawInfo di;
164 if( StartUpdate(&di) )
165 {
166 if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 )
167 {
168 for( uint32_t y = 0; y<m_dwHeight; y++ )
169 {
170 uint32_t* line = (uint32_t*)((uint8_t*)di.lpSurface+di.lPitch*y);
171 uint32_t val = line[m_dwWidth-1];
172 for( uint32_t x=m_dwWidth; x<m_dwCreatedTextureWidth; x++ )
173 line[x] = val;
174 }
175 }
176 else
177 {
178 for( uint32_t y = 0; y<m_dwHeight; y++ )
179 {
180 uint16_t* line = (uint16_t*)((uint8_t*)di.lpSurface+di.lPitch*y);
181 uint16_t val = line[m_dwWidth-1];
182 for( uint32_t x=m_dwWidth; x<m_dwCreatedTextureWidth; x++ )
183 line[x] = val;
184 }
185 }
186 EndUpdate(&di);
187 }
188 }
189 m_bClampedS = true;
190 }
191
ClampImageToSurfaceT()192 void CTexture::ClampImageToSurfaceT()
193 {
194 if( !m_bClampedT && m_dwHeight < m_dwCreatedTextureHeight )
195 {
196 DrawInfo di;
197 if( StartUpdate(&di) )
198 {
199 if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 )
200 {
201 uint32_t* linesrc = (uint32_t*)((uint8_t*)di.lpSurface+di.lPitch*(m_dwHeight-1));
202 for( uint32_t y = m_dwHeight; y<m_dwCreatedTextureHeight; y++ )
203 {
204 uint32_t* linedst = (uint32_t*)((uint8_t*)di.lpSurface+di.lPitch*y);
205 for( uint32_t x=0; x<m_dwCreatedTextureWidth; x++ )
206 linedst[x] = linesrc[x];
207 }
208 }
209 else
210 {
211 uint16_t* linesrc = (uint16_t*)((uint8_t*)di.lpSurface+di.lPitch*(m_dwHeight-1));
212 for( uint32_t y = m_dwHeight; y<m_dwCreatedTextureHeight; y++ )
213 {
214 uint16_t* linedst = (uint16_t*)((uint8_t*)di.lpSurface+di.lPitch*y);
215 for( uint32_t x=0; x<m_dwCreatedTextureWidth; x++ )
216 linedst[x] = linesrc[x];
217 }
218 }
219 EndUpdate(&di);
220 }
221 }
222 m_bClampedT = true;
223 }
224
RestoreAlphaChannel(void)225 void CTexture::RestoreAlphaChannel(void)
226 {
227 DrawInfo di;
228
229 if ( StartUpdate(&di) )
230 {
231 uint32_t *pSrc = (uint32_t *)di.lpSurface;
232 int lPitch = di.lPitch;
233
234 for (uint32_t y = 0; y < m_dwHeight; y++)
235 {
236 uint32_t * dwSrc = (uint32_t *)((uint8_t *)pSrc + y*lPitch);
237 for (uint32_t x = 0; x < m_dwWidth; x++)
238 {
239 uint32_t dw = dwSrc[x];
240 uint32_t dwRed = (uint8_t)((dw & 0x00FF0000)>>16);
241 uint32_t dwGreen = (uint8_t)((dw & 0x0000FF00)>>8 );
242 uint32_t dwBlue = (uint8_t)((dw & 0x000000FF) );
243 uint32_t dwAlpha = (dwRed+dwGreen+dwBlue)/3;
244 dw &= 0x00FFFFFF;
245 dw |= (dwAlpha<<24);
246
247 /*
248 uint32_t dw = dwSrc[x];
249 if( (dw&0x00FFFFFF) > 0 )
250 dw |= 0xFF000000;
251 else
252 dw &= 0x00FFFFFF;
253 */
254 }
255 }
256 EndUpdate(&di);
257 }
258 }
259
260