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