Rice Video Plugin for GLES1.1
[mupen64plus-pandora.git] / source / rice_gles / src / Texture.cpp
CommitLineData
d07c171f 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
28CTexture::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
48CTexture::~CTexture(void)
49{
50}
51
52TextureFmt CTexture::GetSurfaceFormat(void)
53{
54 if (m_pTexture == NULL)
55 return TEXTURE_FMT_UNKNOWN;
56 else
57 return m_dwTextureFmt;
58}
59
60uint32 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
77void 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
163void 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
200void 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
237void 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