11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. |
12 * GNU General Public License for more details. |
13 * |
13 * |
14 * You should have received a copy of the GNU General Public License |
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 |
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 |
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 *) |
17 *) |
18 |
18 |
19 {$INCLUDE "options.inc"} |
19 {$INCLUDE "options.inc"} |
20 |
20 |
21 unit uTextures; |
21 unit uTextures; |
105 fromP4: PLongWordArray; |
106 fromP4: PLongWordArray; |
106 begin |
107 begin |
107 fromP4:= Surf^.pixels; |
108 fromP4:= Surf^.pixels; |
108 for y:= 0 to Pred(Surf^.h) do |
109 for y:= 0 to Pred(Surf^.h) do |
109 begin |
110 begin |
110 for x:= 0 to Pred(Surf^.w) do |
111 for x:= 0 to Pred(Surf^.w) do |
111 begin |
112 begin |
112 tw:= fromP4^[x]; |
113 tw:= fromP4^[x]; |
113 tw:= round((tw shr RShift and $FF) * RGB_LUMINANCE_RED + |
114 tw:= round((tw shr RShift and $FF) * RGB_LUMINANCE_RED + |
114 (tw shr GShift and $FF) * RGB_LUMINANCE_GREEN + |
115 (tw shr GShift and $FF) * RGB_LUMINANCE_GREEN + |
115 (tw shr BShift and $FF) * RGB_LUMINANCE_BLUE); |
116 (tw shr BShift and $FF) * RGB_LUMINANCE_BLUE); |
116 if tw > 255 then tw:= 255; |
117 if tw > 255 then tw:= 255; |
117 tw:= (tw and $FF shl RShift) or (tw and $FF shl BShift) or (tw and $FF shl GShift) or (fromP4^[x] and AMask); |
118 tw:= (tw and $FF shl RShift) or (tw and $FF shl BShift) or (tw and $FF shl GShift) or (fromP4^[x] and AMask); |
118 fromP4^[x]:= tw; |
119 fromP4^[x]:= tw; |
119 end; |
120 end; |
120 fromP4:= @(fromP4^[Surf^.pitch div 4]) |
121 fromP4:= PLongWordArray(@(fromP4^[Surf^.pitch div 4])) |
121 end; |
122 end; |
122 end; |
123 end; |
123 |
124 |
|
125 { this will make invisible pixels that have a visible neighbor have the |
|
126 same color as their visible neighbor, so that bilinear filtering won't |
|
127 display a "wrongly" colored border when zoomed in } |
|
128 procedure PrettifyAlpha(row1, row2: PLongwordArray; firsti, lasti, ioffset: LongWord); |
|
129 var |
|
130 i: Longword; |
|
131 lpi, cpi, bpi: boolean; // was last/current/bottom neighbor pixel invisible? |
|
132 begin |
|
133 // suppress incorrect warning |
|
134 lpi:= true; |
|
135 for i:=firsti to lasti do |
|
136 begin |
|
137 // use first pixel in row1 as starting point |
|
138 if i = firsti then |
|
139 cpi:= ((row1^[i] and AMask) = 0) |
|
140 else |
|
141 begin |
|
142 cpi:= ((row1^[i] and AMask) = 0); |
|
143 if cpi <> lpi then |
|
144 begin |
|
145 // invisible pixels get colors from visible neighbors |
|
146 if cpi then |
|
147 begin |
|
148 row1^[i]:= row1^[i-1] and (not AMask); |
|
149 // as this pixel is invisible and already colored correctly now, no point in further comparing it |
|
150 lpi:= cpi; |
|
151 continue; |
|
152 end |
|
153 else |
|
154 row1^[i-1]:= row1^[i] and (not AMask); |
|
155 end; |
|
156 end; |
|
157 lpi:= cpi; |
|
158 // also check bottom neighbor |
|
159 if row2 <> nil then |
|
160 begin |
|
161 bpi:= ((row2^[i+ioffset] and AMask) = 0); |
|
162 if cpi <> bpi then |
|
163 begin |
|
164 if cpi then |
|
165 row1^[i]:= row2^[i+ioffset] and (not AMask) |
|
166 else |
|
167 row2^[i+ioffset]:= row1^[i] and (not AMask); |
|
168 end; |
|
169 end; |
|
170 end; |
|
171 end; |
|
172 |
|
173 procedure PrettifySurfaceAlpha(surf: PSDL_Surface; pixels: PLongwordArray); |
|
174 var |
|
175 // current row index, second last row index of array, width and first/last i of row |
|
176 r, slr, w, si, li: LongWord; |
|
177 begin |
|
178 w:= surf^.w; |
|
179 slr:= surf^.h - 2; |
|
180 si:= 0; |
|
181 li:= w - 1; |
|
182 for r:= 0 to slr do |
|
183 begin |
|
184 PrettifyAlpha(pixels, pixels, si, li, w); |
|
185 // move indices to next row |
|
186 si:= si + w; |
|
187 li:= li + w; |
|
188 end; |
|
189 // don't forget last row |
|
190 PrettifyAlpha(pixels, nil, si, li, w); |
|
191 end; |
|
192 |
|
193 procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord); |
|
194 var |
|
195 // current y; last x, second last y of array; |
|
196 y, lx, sly: LongWord; |
|
197 begin |
|
198 sly:= height - 2; |
|
199 lx:= width - 1; |
|
200 for y:= 0 to sly do |
|
201 begin |
|
202 PrettifyAlpha(PLongWordArray(pixels[y]), PLongWordArray(pixels[y+1]), 0, lx, 0); |
|
203 end; |
|
204 // don't forget last row |
|
205 PrettifyAlpha(PLongWordArray(pixels[sly+1]), nil, 0, lx, 0); |
|
206 end; |
124 |
207 |
125 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; |
208 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; |
126 var tw, th, x, y: Longword; |
209 var tw, th, x, y: Longword; |
127 tmpp: pointer; |
210 tmpp: pointer; |
128 fromP4, toP4: PLongWordArray; |
211 fromP4, toP4: PLongWordArray; |
177 for y:= 0 to Pred(Surf^.h) do |
261 for y:= 0 to Pred(Surf^.h) do |
178 begin |
262 begin |
179 for x:= 0 to Pred(Surf^.w) do |
263 for x:= 0 to Pred(Surf^.w) do |
180 toP4^[x]:= fromP4^[x]; |
264 toP4^[x]:= fromP4^[x]; |
181 for x:= Surf^.w to Pred(tw) do |
265 for x:= Surf^.w to Pred(tw) do |
182 toP4^[x]:= 0; |
266 toP4^[x]:= fromP4^[0]; |
183 toP4:= @(toP4^[tw]); |
267 toP4:= PLongWordArray(@(toP4^[tw])); |
184 fromP4:= @(fromP4^[Surf^.pitch div 4]) |
268 fromP4:= PLongWordArray(@(fromP4^[Surf^.pitch div 4])) |
185 end; |
269 end; |
186 |
270 |
187 for y:= Surf^.h to Pred(th) do |
271 for y:= Surf^.h to Pred(th) do |
188 begin |
272 begin |
189 for x:= 0 to Pred(tw) do |
273 for x:= 0 to Pred(tw) do |
190 toP4^[x]:= 0; |
274 toP4^[x]:= 0; |
191 toP4:= @(toP4^[tw]) |
275 toP4:= PLongWordArray(@(toP4^[tw])) |
192 end; |
276 end; |
193 |
277 |
194 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpp); |
278 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpp); |
195 |
279 |
196 FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel) |
280 FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel) |
210 SetTextureParameters(enableClamp); |
294 SetTextureParameters(enableClamp); |
211 end; |
295 end; |
212 |
296 |
213 // deletes texture and frees the memory allocated for it. |
297 // deletes texture and frees the memory allocated for it. |
214 // if nil is passed nothing is done |
298 // if nil is passed nothing is done |
215 procedure FreeTexture(tex: PTexture); |
|
216 begin |
|
217 if tex <> nil then |
|
218 begin |
|
219 if tex^.NextTexture <> nil then |
|
220 tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; |
|
221 if tex^.PrevTexture <> nil then |
|
222 tex^.PrevTexture^.NextTexture:= tex^.NextTexture |
|
223 else |
|
224 TextureList:= tex^.NextTexture; |
|
225 glDeleteTextures(1, @tex^.id); |
|
226 Dispose(tex); |
|
227 end |
|
228 end; |
|
229 |
|
230 procedure FreeAndNilTexture(var tex: PTexture); |
299 procedure FreeAndNilTexture(var tex: PTexture); |
231 begin |
300 begin |
232 FreeTexture(tex); |
301 if tex <> nil then |
233 tex:= nil |
302 begin |
|
303 if tex^.NextTexture <> nil then |
|
304 tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; |
|
305 if tex^.PrevTexture <> nil then |
|
306 tex^.PrevTexture^.NextTexture:= tex^.NextTexture |
|
307 else |
|
308 TextureList:= tex^.NextTexture; |
|
309 glDeleteTextures(1, @tex^.id); |
|
310 Dispose(tex); |
|
311 tex:= nil; |
|
312 end; |
234 end; |
313 end; |
235 |
314 |
236 procedure initModule; |
315 procedure initModule; |
237 begin |
316 begin |
238 TextureList:= nil; |
317 TextureList:= nil; |
239 end; |
318 end; |
240 |
319 |
241 procedure freeModule; |
320 procedure freeModule; |
|
321 var tex: PTexture; |
242 begin |
322 begin |
243 if TextureList <> nil then |
323 if TextureList <> nil then |
244 WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem'); |
324 WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem'); |
245 while TextureList <> nil do |
325 while TextureList <> nil do |
246 begin |
326 begin |
247 AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000))); |
327 tex:= TextureList; |
248 FreeTexture(TextureList); |
328 AddFileLog('Texture not freed: width='+inttostr(LongInt(tex^.w))+' height='+inttostr(LongInt(tex^.h))+' priority='+inttostr(round(tex^.priority*1000))); |
|
329 FreeAndNilTexture(tex); |
249 end |
330 end |
250 end; |
331 end; |
251 |
332 |
252 end. |
333 end. |