hedgewars/uTextures.pas
changeset 7080 dbf43c07a507
parent 6982 8d41d22a291d
child 7186 013deb83086b
equal deleted inserted replaced
7079:939f53515489 7080:dbf43c07a507
    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 FreeTexture(tex: PTexture);
       
    29 procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
    29 
    30 
    30 procedure initModule;
    31 procedure initModule;
    31 procedure freeModule;
    32 procedure freeModule;
    32 
    33 
    33 implementation
    34 implementation
    45         end;
    46         end;
    46     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    47     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    47     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    48     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    48 end;
    49 end;
    49 
    50 
       
    51 procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
       
    52 var x0, y0, x1, y1: Real;
       
    53     w, h, aw, ah: LongInt;
       
    54 const texelOffset = 0.0;
       
    55 begin
       
    56 aw:=texture^.atlas^.w;
       
    57 ah:=texture^.atlas^.h;
       
    58 if texture^.isRotated then
       
    59     begin
       
    60     w:=r^.h;
       
    61     h:=r^.w;
       
    62     end 
       
    63 else
       
    64     begin
       
    65     w:=r^.w;
       
    66     h:=r^.h;        
       
    67     end;
       
    68 
       
    69 x0:= (r^.x +     texelOffset)/aw;
       
    70 x1:= (r^.x + w - texelOffset)/aw;
       
    71 y0:= (r^.y +     texelOffset)/ah;
       
    72 y1:= (r^.y + h - texelOffset)/ah;
       
    73 
       
    74 tb^[0].X:= x0;
       
    75 tb^[0].Y:= y0;
       
    76 tb^[1].X:= x1;
       
    77 tb^[1].Y:= y0;
       
    78 tb^[2].X:= x1;
       
    79 tb^[2].Y:= y1;
       
    80 tb^[3].X:= x0;
       
    81 tb^[3].Y:= y1
       
    82 end;
       
    83 
    50 procedure ResetVertexArrays(texture: PTexture);
    84 procedure ResetVertexArrays(texture: PTexture);
       
    85 var r: TSDL_Rect;
    51 begin
    86 begin
    52 with texture^ do
    87 with texture^ do
    53     begin
    88 begin
    54     vb[0].X:= 0;
    89     vb[0].X:= 0;
    55     vb[0].Y:= 0;
    90     vb[0].Y:= 0;
    56     vb[1].X:= w;
    91     vb[1].X:= w;
    57     vb[1].Y:= 0;
    92     vb[1].Y:= 0;
    58     vb[2].X:= w;
    93     vb[2].X:= w;
    59     vb[2].Y:= h;
    94     vb[2].Y:= h;
    60     vb[3].X:= 0;
    95     vb[3].X:= 0;
    61     vb[3].Y:= h;
    96     vb[3].Y:= h;
    62 
    97 end;
    63     tb[0].X:= 0;
    98 
    64     tb[0].Y:= 0;
    99 r.x:= 0;
    65     tb[1].X:= rx;
   100 r.y:= 0;
    66     tb[1].Y:= 0;
   101 r.w:= texture^.w;
    67     tb[2].X:= rx;
   102 r.h:= texture^.h;
    68     tb[2].Y:= ry;
   103 ComputeTexcoords(texture, @r, @texture^.tb);
    69     tb[3].X:= 0;
       
    70     tb[3].Y:= ry
       
    71     end;
       
    72 end;
   104 end;
    73 
   105 
    74 function NewTexture(width, height: Longword; buf: Pointer): PTexture;
   106 function NewTexture(width, height: Longword; buf: Pointer): PTexture;
    75 begin
   107 begin
    76 new(NewTexture);
   108 new(NewTexture);
    82     TextureList^.PrevTexture:= NewTexture;
   114     TextureList^.PrevTexture:= NewTexture;
    83     NewTexture^.NextTexture:= TextureList
   115     NewTexture^.NextTexture:= TextureList
    84     end;
   116     end;
    85 TextureList:= NewTexture;
   117 TextureList:= NewTexture;
    86 
   118 
    87 NewTexture^.w:= width;
   119 
    88 NewTexture^.h:= height;
   120 // Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
    89 NewTexture^.rx:= 1.0;
   121 new(NewTexture^.atlas);
    90 NewTexture^.ry:= 1.0;
   122 NewTexture^.atlas^.w:=width;
       
   123 NewTexture^.atlas^.h:=height;
       
   124 NewTexture^.x:=0;
       
   125 NewTexture^.y:=0;
       
   126 NewTexture^.w:=width;
       
   127 NewTexture^.h:=height;
       
   128 NewTexture^.isRotated:=false;
    91 
   129 
    92 ResetVertexArrays(NewTexture);
   130 ResetVertexArrays(NewTexture);
    93 
   131 
    94 glGenTextures(1, @NewTexture^.id);
   132 glGenTextures(1, @NewTexture^.atlas^.id);
    95 
   133 
    96 glBindTexture(GL_TEXTURE_2D, NewTexture^.id);
   134 glBindTexture(GL_TEXTURE_2D, NewTexture^.atlas^.id);
    97 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
   135 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
    98 
   136 
    99 SetTextureParameters(true);
   137 SetTextureParameters(true);
   100 end;
   138 end;
   101 
   139 
   134     TextureList^.PrevTexture:= Surface2Tex;
   172     TextureList^.PrevTexture:= Surface2Tex;
   135     Surface2Tex^.NextTexture:= TextureList
   173     Surface2Tex^.NextTexture:= TextureList
   136     end;
   174     end;
   137 TextureList:= Surface2Tex;
   175 TextureList:= Surface2Tex;
   138 
   176 
       
   177 // Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
       
   178 new(Surface2Tex^.atlas);
       
   179 
   139 Surface2Tex^.w:= surf^.w;
   180 Surface2Tex^.w:= surf^.w;
   140 Surface2Tex^.h:= surf^.h;
   181 Surface2Tex^.h:= surf^.h;
       
   182 Surface2Tex^.x:=0;
       
   183 Surface2Tex^.y:=0;
       
   184 Surface2Tex^.isRotated:=false;
       
   185 
   141 
   186 
   142 if (surf^.format^.BytesPerPixel <> 4) then
   187 if (surf^.format^.BytesPerPixel <> 4) then
   143     begin
   188     begin
   144     TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
   189     TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
   145     Surface2Tex^.id:= 0;
   190     Surface2Tex^.atlas^.id:= 0;
   146     exit
   191     exit
   147     end;
   192     end;
   148 
   193 
   149 
   194 
   150 glGenTextures(1, @Surface2Tex^.id);
   195 glGenTextures(1, @Surface2Tex^.atlas^.id);
   151 
   196 
   152 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
   197 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.atlas^.id);
   153 
   198 
   154 if SDL_MustLock(surf) then
   199 if SDL_MustLock(surf) then
   155     SDLTry(SDL_LockSurface(surf) >= 0, true);
   200     SDLTry(SDL_LockSurface(surf) >= 0, true);
   156 
   201 
   157 fromP4:= Surf^.pixels;
   202 fromP4:= Surf^.pixels;
   162 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
   207 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
   163     begin
   208     begin
   164     tw:= toPowerOf2(Surf^.w);
   209     tw:= toPowerOf2(Surf^.w);
   165     th:= toPowerOf2(Surf^.h);
   210     th:= toPowerOf2(Surf^.h);
   166 
   211 
   167     Surface2Tex^.rx:= Surf^.w / tw;
   212     Surface2Tex^.atlas^.w:=tw;
   168     Surface2Tex^.ry:= Surf^.h / th;
   213     Surface2Tex^.atlas^.h:=th;
   169 
   214 
   170     GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel);
   215     GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel);
   171 
   216 
   172     fromP4:= Surf^.pixels;
   217     fromP4:= Surf^.pixels;
   173     toP4:= tmpp;
   218     toP4:= tmpp;
   193 
   238 
   194     FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel)
   239     FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel)
   195     end
   240     end
   196 else
   241 else
   197     begin
   242     begin
   198     Surface2Tex^.rx:= 1.0;
   243     Surface2Tex^.atlas^.w:=Surf^.w;
   199     Surface2Tex^.ry:= 1.0;
   244     Surface2Tex^.atlas^.h:=Surf^.h;
   200     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
   245     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
   201     end;
   246     end;
   202 
   247 
   203 ResetVertexArrays(Surface2Tex);
   248 ResetVertexArrays(Surface2Tex);
   204 
   249 
   212 // if nil is passed nothing is done
   257 // if nil is passed nothing is done
   213 procedure FreeTexture(tex: PTexture);
   258 procedure FreeTexture(tex: PTexture);
   214 begin
   259 begin
   215 if tex <> nil then
   260 if tex <> nil then
   216     begin
   261     begin
       
   262     // Atlas cleanup happens here later on. For now we just free as each sprite has one atlas
       
   263     Dispose(tex^.atlas);
       
   264 
   217     if tex^.NextTexture <> nil then
   265     if tex^.NextTexture <> nil then
   218         tex^.NextTexture^.PrevTexture:= tex^.PrevTexture;
   266         tex^.NextTexture^.PrevTexture:= tex^.PrevTexture;
   219     if tex^.PrevTexture <> nil then
   267     if tex^.PrevTexture <> nil then
   220         tex^.PrevTexture^.NextTexture:= tex^.NextTexture
   268         tex^.PrevTexture^.NextTexture:= tex^.NextTexture
   221     else
   269     else
   222         TextureList:= tex^.NextTexture;
   270         TextureList:= tex^.NextTexture;
   223     glDeleteTextures(1, @tex^.id);
   271     glDeleteTextures(1, @tex^.atlas^.id);
   224     Dispose(tex);
   272     Dispose(tex);
   225     end
   273     end
   226 end;
   274 end;
   227 
   275 
   228 procedure initModule;
   276 procedure initModule;
   234 begin
   282 begin
   235 if TextureList <> nil then
   283 if TextureList <> nil then
   236     WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem');
   284     WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem');
   237     while TextureList <> nil do 
   285     while TextureList <> nil do 
   238         begin
   286         begin
   239         AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000)));
   287         AddFileLog('Sprite not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.atlas^.priority*1000)));
   240         FreeTexture(TextureList);
   288         FreeTexture(TextureList);
   241         end
   289         end
   242 end;
   290 end;
   243 
   291 
   244 end.
   292 end.