hedgewars/uTextures.pas
branchsdl2transition
changeset 11362 ed5a6478e710
parent 9682 aa2431ed87b2
parent 11317 62287d4044e7
child 11487 8e221d2a368e
equal deleted inserted replaced
11361:31570b766315 11362:ed5a6478e710
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    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;
    23 uses SDLh, uTypes;
    23 uses SDLh, uTypes;
    24 
    24 
    25 function  NewTexture(width, height: Longword; buf: Pointer): PTexture;
    25 function  NewTexture(width, height: Longword; buf: Pointer): PTexture;
    26 procedure Surface2GrayScale(surf: PSDL_Surface);
    26 procedure Surface2GrayScale(surf: PSDL_Surface);
    27 function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
    27 function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
    28 procedure FreeTexture(tex: PTexture);
    28 procedure PrettifySurfaceAlpha(surf: PSDL_Surface; pixels: PLongwordArray);
       
    29 procedure PrettifyAlpha2D(pixels: TLandArray; height, width: LongWord);
    29 procedure FreeAndNilTexture(var tex: PTexture);
    30 procedure FreeAndNilTexture(var tex: PTexture);
    30 
    31 
    31 procedure initModule;
    32 procedure initModule;
    32 procedure freeModule;
    33 procedure freeModule;
    33 
    34 
   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;
   146     TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
   229     TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
   147     Surface2Tex^.id:= 0;
   230     Surface2Tex^.id:= 0;
   148     exit
   231     exit
   149     end;
   232     end;
   150 
   233 
   151 
       
   152 glGenTextures(1, @Surface2Tex^.id);
   234 glGenTextures(1, @Surface2Tex^.id);
   153 
   235 
   154 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
   236 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
   155 
   237 
   156 if SDL_MustLock(surf) then
   238 if SDL_MustLock(surf) then
   158 
   240 
   159 fromP4:= Surf^.pixels;
   241 fromP4:= Surf^.pixels;
   160 
   242 
   161 if GrayScale then
   243 if GrayScale then
   162     Surface2GrayScale(Surf);
   244     Surface2GrayScale(Surf);
       
   245 
       
   246 PrettifySurfaceAlpha(surf, fromP4);
   163 
   247 
   164 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
   248 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
   165     begin
   249     begin
   166     tw:= toPowerOf2(Surf^.w);
   250     tw:= toPowerOf2(Surf^.w);
   167     th:= toPowerOf2(Surf^.h);
   251     th:= toPowerOf2(Surf^.h);
   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.