| 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 | |
| 28 | CTexture::CTexture(uint32 dwWidth, uint32 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 | |
| 48 | CTexture::~CTexture(void) |
| 49 | { |
| 50 | } |
| 51 | |
| 52 | TextureFmt CTexture::GetSurfaceFormat(void) |
| 53 | { |
| 54 | if (m_pTexture == NULL) |
| 55 | return TEXTURE_FMT_UNKNOWN; |
| 56 | else |
| 57 | return m_dwTextureFmt; |
| 58 | } |
| 59 | |
| 60 | uint32 CTexture::GetPixelSize() |
| 61 | { |
| 62 | if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 ) |
| 63 | return 4; |
| 64 | else |
| 65 | return 2; |
| 66 | } |
| 67 | |
| 68 | |
| 69 | // There are reasons to create this function. D3D and OGL will only create surface of width and height |
| 70 | // as 2's pow, for example, N64's 20x14 image, D3D and OGL will create a 32x16 surface. |
| 71 | // When we using such a surface as D3D texture, and the U and V address is for the D3D and OGL surface |
| 72 | // width and height. It is still OK if the U and V addr value is less than the real image within |
| 73 | // the D3D surface. But we will have problems if the U and V addr value is larger than it, or even |
| 74 | // large then 1.0. |
| 75 | // In such a case, we need to scale the image to the D3D surface dimension, to ease the U/V addr |
| 76 | // limition |
| 77 | void CTexture::ScaleImageToSurface(bool scaleS, bool scaleT) |
| 78 | { |
| 79 | uint8 g_ucTempBuffer[1024*1024*4]; |
| 80 | |
| 81 | if( scaleS==false && scaleT==false) return; |
| 82 | |
| 83 | // If the image is not scaled, call this function to scale the real image to |
| 84 | // the D3D given dimension |
| 85 | |
| 86 | uint32 width = scaleS ? m_dwWidth : m_dwCreatedTextureWidth; |
| 87 | uint32 height = scaleT ? m_dwHeight : m_dwCreatedTextureHeight; |
| 88 | |
| 89 | uint32 xDst, yDst; |
| 90 | uint32 xSrc, ySrc; |
| 91 | |
| 92 | DrawInfo di; |
| 93 | |
| 94 | if (!StartUpdate(&di)) |
| 95 | { |
| 96 | return; |
| 97 | } |
| 98 | |
| 99 | int pixSize = GetPixelSize(); |
| 100 | |
| 101 | // Copy across from the temp buffer to the surface |
| 102 | switch (pixSize) |
| 103 | { |
| 104 | case 4: |
| 105 | { |
| 106 | memcpy((uint8*)g_ucTempBuffer, (uint8*)(di.lpSurface), m_dwHeight*m_dwCreatedTextureWidth*4); |
| 107 | |
| 108 | uint32 * pDst; |
| 109 | uint32 * pSrc; |
| 110 | |
| 111 | for (yDst = 0; yDst < m_dwCreatedTextureHeight; yDst++) |
| 112 | { |
| 113 | // ySrc ranges from 0..m_dwHeight |
| 114 | // I'd rather do this but sometimes very narrow (i.e. 1 pixel) |
| 115 | // surfaces are created which results in /0... |
| 116 | //ySrc = (yDst * (m_dwHeight-1)) / (d3dTextureHeight-1); |
| 117 | ySrc = (uint32)((yDst * height) / m_dwCreatedTextureHeight+0.49f); |
| 118 | |
| 119 | pSrc = (uint32*)((uint8*)g_ucTempBuffer + (ySrc * m_dwCreatedTextureWidth * 4)); |
| 120 | pDst = (uint32*)((uint8*)di.lpSurface + (yDst * di.lPitch)); |
| 121 | |
| 122 | for (xDst = 0; xDst < m_dwCreatedTextureWidth; xDst++) |
| 123 | { |
| 124 | xSrc = (uint32)((xDst * width) / m_dwCreatedTextureWidth+0.49f); |
| 125 | pDst[xDst] = pSrc[xSrc]; |
| 126 | } |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | break; |
| 131 | case 2: |
| 132 | { |
| 133 | memcpy((uint8*)g_ucTempBuffer, (uint8*)(di.lpSurface), m_dwHeight*m_dwCreatedTextureWidth*2); |
| 134 | |
| 135 | uint16 * pDst; |
| 136 | uint16 * pSrc; |
| 137 | |
| 138 | for (yDst = 0; yDst < m_dwCreatedTextureHeight; yDst++) |
| 139 | { |
| 140 | // ySrc ranges from 0..m_dwHeight |
| 141 | ySrc = (yDst * height) / m_dwCreatedTextureHeight; |
| 142 | |
| 143 | pSrc = (uint16*)((uint8*)g_ucTempBuffer + (ySrc * m_dwCreatedTextureWidth * 2)); |
| 144 | pDst = (uint16*)((uint8*)di.lpSurface + (yDst * di.lPitch)); |
| 145 | |
| 146 | for (xDst = 0; xDst < m_dwCreatedTextureWidth; xDst++) |
| 147 | { |
| 148 | xSrc = (xDst * width) / m_dwCreatedTextureWidth; |
| 149 | pDst[xDst] = pSrc[xSrc]; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | break; |
| 154 | |
| 155 | } |
| 156 | |
| 157 | EndUpdate(&di); |
| 158 | |
| 159 | if( scaleS ) m_bScaledS = true; |
| 160 | if( scaleT ) m_bScaledT = true; |
| 161 | } |
| 162 | |
| 163 | void CTexture::ClampImageToSurfaceS() |
| 164 | { |
| 165 | if( !m_bClampedS && m_dwWidth < m_dwCreatedTextureWidth ) |
| 166 | { |
| 167 | DrawInfo di; |
| 168 | if( StartUpdate(&di) ) |
| 169 | { |
| 170 | if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 ) |
| 171 | { |
| 172 | for( uint32 y = 0; y<m_dwHeight; y++ ) |
| 173 | { |
| 174 | uint32* line = (uint32*)((uint8*)di.lpSurface+di.lPitch*y); |
| 175 | uint32 val = line[m_dwWidth-1]; |
| 176 | for( uint32 x=m_dwWidth; x<m_dwCreatedTextureWidth; x++ ) |
| 177 | { |
| 178 | line[x] = val; |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | else |
| 183 | { |
| 184 | for( uint32 y = 0; y<m_dwHeight; y++ ) |
| 185 | { |
| 186 | uint16* line = (uint16*)((uint8*)di.lpSurface+di.lPitch*y); |
| 187 | uint16 val = line[m_dwWidth-1]; |
| 188 | for( uint32 x=m_dwWidth; x<m_dwCreatedTextureWidth; x++ ) |
| 189 | { |
| 190 | line[x] = val; |
| 191 | } |
| 192 | } |
| 193 | } |
| 194 | EndUpdate(&di); |
| 195 | } |
| 196 | } |
| 197 | m_bClampedS = true; |
| 198 | } |
| 199 | |
| 200 | void CTexture::ClampImageToSurfaceT() |
| 201 | { |
| 202 | if( !m_bClampedT && m_dwHeight < m_dwCreatedTextureHeight ) |
| 203 | { |
| 204 | DrawInfo di; |
| 205 | if( StartUpdate(&di) ) |
| 206 | { |
| 207 | if( m_dwTextureFmt == TEXTURE_FMT_A8R8G8B8 ) |
| 208 | { |
| 209 | uint32* linesrc = (uint32*)((uint8*)di.lpSurface+di.lPitch*(m_dwHeight-1)); |
| 210 | for( uint32 y = m_dwHeight; y<m_dwCreatedTextureHeight; y++ ) |
| 211 | { |
| 212 | uint32* linedst = (uint32*)((uint8*)di.lpSurface+di.lPitch*y); |
| 213 | for( uint32 x=0; x<m_dwCreatedTextureWidth; x++ ) |
| 214 | { |
| 215 | linedst[x] = linesrc[x]; |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | else |
| 220 | { |
| 221 | uint16* linesrc = (uint16*)((uint8*)di.lpSurface+di.lPitch*(m_dwHeight-1)); |
| 222 | for( uint32 y = m_dwHeight; y<m_dwCreatedTextureHeight; y++ ) |
| 223 | { |
| 224 | uint16* linedst = (uint16*)((uint8*)di.lpSurface+di.lPitch*y); |
| 225 | for( uint32 x=0; x<m_dwCreatedTextureWidth; x++ ) |
| 226 | { |
| 227 | linedst[x] = linesrc[x]; |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | EndUpdate(&di); |
| 232 | } |
| 233 | } |
| 234 | m_bClampedT = true; |
| 235 | } |
| 236 | |
| 237 | void CTexture::RestoreAlphaChannel(void) |
| 238 | { |
| 239 | DrawInfo di; |
| 240 | |
| 241 | if ( StartUpdate(&di) ) |
| 242 | { |
| 243 | uint32 *pSrc = (uint32 *)di.lpSurface; |
| 244 | int lPitch = di.lPitch; |
| 245 | |
| 246 | for (uint32 y = 0; y < m_dwHeight; y++) |
| 247 | { |
| 248 | uint32 * dwSrc = (uint32 *)((uint8 *)pSrc + y*lPitch); |
| 249 | for (uint32 x = 0; x < m_dwWidth; x++) |
| 250 | { |
| 251 | uint32 dw = dwSrc[x]; |
| 252 | uint32 dwRed = (uint8)((dw & 0x00FF0000)>>16); |
| 253 | uint32 dwGreen = (uint8)((dw & 0x0000FF00)>>8 ); |
| 254 | uint32 dwBlue = (uint8)((dw & 0x000000FF) ); |
| 255 | uint32 dwAlpha = (dwRed+dwGreen+dwBlue)/3; |
| 256 | dw &= 0x00FFFFFF; |
| 257 | dw |= (dwAlpha<<24); |
| 258 | |
| 259 | /* |
| 260 | uint32 dw = dwSrc[x]; |
| 261 | if( (dw&0x00FFFFFF) > 0 ) |
| 262 | dw |= 0xFF000000; |
| 263 | else |
| 264 | dw &= 0x00FFFFFF; |
| 265 | */ |
| 266 | } |
| 267 | } |
| 268 | EndUpdate(&di); |
| 269 | } |
| 270 | else |
| 271 | { |
| 272 | //TRACE0("Cannot lock texture"); |
| 273 | } |
| 274 | } |
| 275 | |