Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / Texture.cpp
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