// deprecated, use DDrawTex
{$ERROR DGraphTex is deprecated, use DDrawTex instead}
{$i deng_defines.inc}
unit DGraphTex;

interface

uses
  {$IFDEF DENG_USE_DRAW_OPENGL}{$IFDEF ANDROID}GLES,{$ELSE}GL, GLU,{$ENDIF}{$ENDIF}
  dtypes,
  dstrnum,
  dstream,
  dscreenbuffer,
  dtexture2d,
  dvector2f,
  dvector2i,
  DDraw;

type
TGraphTex = packed object
  {$IFDEF DENG_USE_DRAW_OPENGL}Id: GLuint;{$ENDIF}
  Width: Integer;
  Height: Integer;
  function Size: TVec2f; inline;
end;

TGraphTexHelper = class helper for TGraph
  function UploadTex(Texture: TTexture2d; MipMap: Boolean = True): TGraphTex; overload;
  function UploadTex(Buffer: PScreenBuffer; MipMap: Boolean = True): TGraphTex; overload;
  function UploadTex(Data: TData; MipMap: Boolean = True): TGraphTex; overload;
  procedure FreeTex(const T: TGraphTex);
  procedure BindTex(const T: TGraphTex);
  procedure UnbindTex;
  // draw centered texture
  // TODO rename: DrawTex -> Tex
  procedure DrawTex(const T: TGraphTex; const P: TVec2f); overload;
  procedure Tex(const T: TGraphTex; const P: TVec2f); overload;
  procedure DrawTex(const T: TGraphTex; const P, S: TVec2f); overload;
  procedure Tex(const T: TGraphTex; const P, S: TVec2f); overload;
  procedure DrawTex(const T: TGraphTex;
        const P, S: TVec2f;
        Angle: TFloat); overload;
  procedure DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2f); overload;
  procedure DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i); overload;
  procedure DrawTexLT(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i); overload;
  procedure DrawTex(const Tex: TGraphTex;
        const P, S: TVec2i;
		const T, R: TVec2i;
        Angle: TFloat); overload;
  procedure DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i;
        Angle: TFloat); overload;
  procedure Tex(const T: TGraphTex;
        const P, Dir: TVec2f;
        const A, B: TVec2i;
        FlipX, FlipY: Boolean); overload;
end;

implementation

uses
{$IFDEF ANDROID}
  DDrawVertexBuffer,
{$ENDIF}
  DEng,
  DMetrics;

{$IFDEF DENG_USE_DRAW_OPENGL}
function TGraphTex.Size: TVec2f;
begin
  Result := Vec2f(Width, Height);
end;

function TGraphTexHelper.UploadTex(Texture: TTexture2d; MipMap: Boolean = True): TGraphTex;
{$IFDEF ANDROID}
const
  GL_RGBA8 = GL_RGBA;
{$ENDIF}
var
  Dur: TMetricDuration;
begin
  Dur.Init('texture_upload_dt');
  Result.Width := Texture.Width;
  Result.Height := Texture.Height;
  glGenTextures(1, @Result.Id);
  glBindTexture(GL_TEXTURE_2D, Result.Id);
  //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // set 1-byte alignment

  {$IFNDEF ANDROID}
  if MipMap then
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
                      Texture.Width, Texture.Height, GL_RGBA,
                      GL_UNSIGNED_BYTE, Texture.Data)
  else
  {$ENDIF}
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                 Texture.Width, Texture.Height, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, Texture.Data);
  //Log('MARKER TEXTURE PTR = ' + IntToStr(PtrUInt(Texture.Data)));

  // set texture to repeat mode
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

  if MipMap then begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    {$IFDEF ANDROID}
    //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    {$ENDIF}
  end else begin
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  end;
  //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0);
  glDisable(GL_LIGHTING);
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_DITHER);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  glBindTexture(GL_TEXTURE_2D, 0);
  Dur.Done;
end;

function TGraphTexHelper.UploadTex(Buffer: PScreenBuffer; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2dRaw;
begin
  T := TTexture2dRaw.Create(Buffer);
  Result := Self.UploadTex(TTexture2d(T), MipMap);
  T.Free;
end;

{function TGraphTexHelper.UploadTex(const FileName: TString; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2d;
begin
  if not LoadTexture2d(FileName, T) then begin
    Result.Id := 0;
    Result.Width := 0;
    Result.Height := 0;
  end else begin
    Result := UploadTex(T, MipMap);
    T.Free;
  end;
end;}

function TGraphTexHelper.UploadTex(Data: TData; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2d;
begin
  if not LoadTexture2d(Data.Stream, T) then begin
    Result.Id := 0;
    Result.Width := 0;
    Result.Height := 0;
  end else begin
    Result := UploadTex(T, MipMap);
    T.Free;
  end;
  Data.Done;
end;

procedure TGraphTexHelper.FreeTex(const T: TGraphTex);
begin
  glDeleteTextures(1, @T.Id);
end;

procedure TGraphTexHelper.BindTex(const T: TGraphTex);
begin
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, T.Id);
end;

procedure TGraphTexHelper.UnbindTex;
begin
  glDisable(GL_TEXTURE_2D);
end;

procedure TGraphTexHelper.DrawTex(const T: TGraphTex; const P: TVec2f);
begin
  DrawTex(T, P, Vec2f(T.Width, T.Height));
end;

procedure TGraphTexHelper.Tex(const T: TGraphTex; const P: TVec2f);
begin
  Tex(T, P, Vec2f(T.Width, T.Height));
end;

procedure TGraphTexHelper.DrawTex(const T: TGraphTex; const P, S: TVec2f);
begin
  Tex(T, P, S);
end;

procedure TGraphTexHelper.Tex(const T: TGraphTex; const P, S: TVec2f);
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
begin
  BindTex(T);
  TexCoords2f[0] := Vec2f(0, 0);
  TexCoords2f[1] := Vec2f(1, 0);
  TexCoords2f[2] := Vec2f(1, 1);
  TexCoords2f[3] := Vec2f(0, 1);
  Vertices2f[0] := Vec2f(P.X - S.X / 2, P.Y - S.Y / 2);
  Vertices2f[1] := Vec2f(P.X + S.X / 2, P.Y - S.Y / 2);
  Vertices2f[2] := Vec2f(P.X + S.X / 2, P.Y + S.Y / 2);
  Vertices2f[3] := Vec2f(P.X - S.X / 2, P.Y + S.Y / 2);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
  UnbindTex;
end;
{$ELSE}
begin
  BindTex(T);
  glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex2f(P.X - S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(1, 0);
    glVertex2f(P.X + S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(1, 1);
    glVertex2f(P.X + S.X / 2, P.Y + S.Y / 2);
    glTexCoord2f(0, 1);
    glVertex2f(P.X - S.X / 2, P.Y + S.Y / 2);
  glEnd;
  UnbindTex;
end;
{$ENDIF}

procedure TGraphTexHelper.DrawTex(const T: TGraphTex;
      const P, S: TVec2f;
      Angle: TFloat);
var
  _S, _C: TFloat;
begin
  {$IFNDEF ANDROID}
  BindTex(T);
  _C := Cos(Angle) / 2;
  _S := Sin(Angle) / 2;
  glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex2f(P.X - _C * S.X + _S * S.Y, P.Y - _C * S.Y - _S * S.X);
    glTexCoord2f(1, 0);
    glVertex2f(P.X + _C * S.X + _S * S.Y, P.Y - _C * S.Y + _S * S.X);
    glTexCoord2f(1, 1);
    glVertex2f(P.X + _C * S.X - _S * S.Y, P.Y + _C * S.Y + _S * S.X);
    glTexCoord2f(0, 1);
    glVertex2f(P.X - _C * S.X - _S * S.Y, P.Y + _C * S.Y - _S * S.X);
  glEnd;
  UnbindTex;
  {$ENDIF}
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2f);
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
begin
  BindTex(Tex);
  TexCoords2f[0] := Vec2f(T.X, T.Y);
  TexCoords2f[1] := Vec2f(T.X + R.X, T.Y);
  TexCoords2f[2] := Vec2f(T.X + R.X, T.Y + R.Y);
  TexCoords2f[3] := Vec2f(T.X, T.Y + R.Y);
  Vertices2f[0] := Vec2f(P.X - S.X / 2, P.Y - S.Y / 2);
  Vertices2f[1] := Vec2f(P.X + S.X / 2, P.Y - S.Y / 2);
  Vertices2f[2] := Vec2f(P.X + S.X / 2, P.Y + S.Y / 2);
  Vertices2f[3] := Vec2f(P.X - S.X / 2, P.Y + S.Y / 2);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
  UnbindTex;
end;
{$ELSE}
begin
  BindTex(Tex);
  glBegin(GL_QUADS);
    glTexCoord2f(T.X, T.Y);
    glVertex2f(P.X - S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(T.X + R.X, T.Y);
    glVertex2f(P.X + S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(T.X + R.X, T.Y + R.Y);
    glVertex2f(P.X + S.X / 2, P.Y + S.Y / 2);
    glTexCoord2f(T.X, T.Y + R.Y);
    glVertex2f(P.X - S.X / 2, P.Y + S.Y / 2);
  glEnd;
  UnbindTex;
end;
{$ENDIF}

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i);
var
  X1, Y1, X2, Y2: Single;
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  TexCoords2f[0] := Vec2f(X1, Y1);
  TexCoords2f[1] := Vec2f(X2, Y1);
  TexCoords2f[2] := Vec2f(X2, Y2);
  TexCoords2f[3] := Vec2f(X1, Y2);
  Vertices2f[0] := Vec2f(P.X - S.X / 2, P.Y - S.Y / 2);
  Vertices2f[1] := Vec2f(P.X + S.X / 2, P.Y - S.Y / 2);
  Vertices2f[2] := Vec2f(P.X + S.X / 2, P.Y + S.Y / 2);
  Vertices2f[3] := Vec2f(P.X - S.X / 2, P.Y + S.Y / 2);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
  UnbindTex;
end;
{$ELSE}
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  glBegin(GL_QUADS);
    glTexCoord2f(X1, Y1);
    glVertex2f(P.X - S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(X2, Y1);
    glVertex2f(P.X + S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(X2, Y2);
    glVertex2f(P.X + S.X / 2, P.Y + S.Y / 2);
    glTexCoord2f(X1, Y2);
    glVertex2f(P.X - S.X / 2, P.Y + S.Y / 2);
  glEnd;
  UnbindTex;
end;
{$ENDIF}

procedure TGraphTexHelper.DrawTexLT(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i);
var
  X1, Y1, X2, Y2: Single;
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  TexCoords2f[0] := Vec2f(X1, Y1);
  TexCoords2f[1] := Vec2f(X2, Y1);
  TexCoords2f[2] := Vec2f(X2, Y2);
  TexCoords2f[3] := Vec2f(X1, Y2);
  Vertices2f[0] := Vec2f(P.X      , P.Y      );
  Vertices2f[1] := Vec2f(P.X + S.X, P.Y      );
  Vertices2f[2] := Vec2f(P.X + S.X, P.Y + S.Y);
  Vertices2f[3] := Vec2f(P.X      , P.Y + S.Y);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
  UnbindTex;
end;
{$ELSE}
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  glBegin(GL_QUADS);
    glTexCoord2f(X1, Y1);
    glVertex2f(P.X      , P.Y      );
    glTexCoord2f(X2, Y1);
    glVertex2f(P.X + S.X, P.Y      );
    glTexCoord2f(X2, Y2);
    glVertex2f(P.X + S.X, P.Y + S.Y);
    glTexCoord2f(X1, Y2);
    glVertex2f(P.X      , P.Y + S.Y);
  glEnd;
  UnbindTex;
end;
{$ENDIF}

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
      const P, S: TVec2i;
      const T, R: TVec2i;
      Angle: TFloat);
begin
  DrawTex(Tex, Vec2f(P.X, P.Y), Vec2f(S.X, S.Y), T, R, Angle);
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
    const P, S: TVec2f;
    const T, R: TVec2i;
    Angle: TFloat);
var
  X1, Y1, X2, Y2: Single;
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  TexCoords2f[0] := Vec2f(X1, Y1);
  TexCoords2f[1] := Vec2f(X2, Y1);
  TexCoords2f[2] := Vec2f(X2, Y2);
  TexCoords2f[3] := Vec2f(X1, Y2);
  Vertices2f[0] := Vec2f(P.X - S.X / 2, P.Y - S.Y / 2);
  Vertices2f[1] := Vec2f(P.X + S.X / 2, P.Y - S.Y / 2);
  Vertices2f[2] := Vec2f(P.X + S.X / 2, P.Y + S.Y / 2);
  Vertices2f[3] := Vec2f(P.X - S.X / 2, P.Y + S.Y / 2);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
  UnbindTex;
end;
{$ELSE}
begin
  X1 := T.X / Tex.Width;
  Y1 := T.Y / Tex.Height;
  X2 := (T.X + R.X) / Tex.Width;
  Y2 := (T.Y + R.Y) / Tex.Height;
  BindTex(Tex);
  glBegin(GL_QUADS);
    glTexCoord2f(X1, Y1);
    glVertex2f(P.X - S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(X2, Y1);
    glVertex2f(P.X + S.X / 2, P.Y - S.Y / 2);
    glTexCoord2f(X2, Y2);
    glVertex2f(P.X + S.X / 2, P.Y + S.Y / 2);
    glTexCoord2f(X1, Y2);
    glVertex2f(P.X - S.X / 2, P.Y + S.Y / 2);
  glEnd;
  UnbindTex;
end;
{$ENDIF}

procedure TGraphTexHelper.Tex(const T: TGraphTex;
	const P, Dir: TVec2f;
	const A, B: TVec2i;
	FlipX, FlipY: Boolean);
var
  X1, Y1, X2, Y2: Single;
  Temp: Single;
  Nor: TVec2f;
{$IFDEF ANDROID}
var
  Vertices2f: array[0..3] of TVec2f;
	TexCoords2f: array[0..3] of TVec2f;
	Indices: array[0..5] of TIndexBuffer.TIndex;
	VB: TVertexBuffer;
	IB: TIndexBuffer;
{$ENDIF}
begin
  if T.Width > 0 then begin
    X1 := A.X / T.Width;
    X2 := (A.X + B.X) / T.Width;
  end else begin
    X1 := 0;
    X2 := 0;
  end;
  if T.Height > 0 then begin
    Y1 := A.Y / T.Height;
    Y2 := (A.Y + B.Y) / T.Height;
  end else begin
    Y1 := 0;
    Y2 := 0;
  end;
  if FlipX then begin
    Temp := X1;
	X1 := X2;
	X2 := Temp;
  end;
  if FlipY then begin
    Temp := Y1;
	Y1 := Y2;
	Y2 := Temp;
  end;
  Nor := Vec2f(- Dir.Y, Dir.X);
  BindTex(T);
  {$IFDEF ANDROID}
  TexCoords2f[0] := Vec2f(X1, Y1);
  TexCoords2f[1] := Vec2f(X2, Y1);
  TexCoords2f[2] := Vec2f(X2, Y2);
  TexCoords2f[3] := Vec2f(X1, Y2);
  Vertices2f[0] := Vec2f(P.X - Dir.X - Nor.X, P.Y - Dir.Y - Nor.Y);
  Vertices2f[1] := Vec2f(P.X + Dir.X - Nor.X, P.Y + Dir.Y - Nor.Y);
  Vertices2f[2] := Vec2f(P.X + Dir.X + Nor.X, P.Y + Dir.Y + Nor.Y);
  Vertices2f[3] := Vec2f(P.X - Dir.X + Nor.X, P.Y - Dir.Y + Nor.Y);
	VB.Init(Vertices2f);
	VB.SetTexCoords(TexCoords2f);
  Indices[0] := 0; Indices[1] := 1; Indices[2] := 3;
  Indices[3] := 1; Indices[4] := 2; Indices[5] := 3;
  IB.Init(Indices);
	VB.DrawTriangles(IB);
	IB.Done;
	VB.Done;
	{$ELSE}
  glBegin(GL_QUADS);
    glTexCoord2f(X1, Y1);
    glVertex2f(P.X - Dir.X - Nor.X, P.Y - Dir.Y - Nor.Y);
    glTexCoord2f(X2, Y1);
    glVertex2f(P.X + Dir.X - Nor.X, P.Y + Dir.Y - Nor.Y);
    glTexCoord2f(X2, Y2);
    glVertex2f(P.X + Dir.X + Nor.X, P.Y + Dir.Y + Nor.Y);
    glTexCoord2f(X1, Y2);
    glVertex2f(P.X - Dir.X + Nor.X, P.Y - Dir.Y + Nor.Y);
  glEnd;
  {$ENDIF}
  UnbindTex;
end;
{$ENDIF}

{$IF Defined(DENG_USE_NODRAW)}
function TGraphTex.Size: TVec2f;
begin
  Result := Vec2f(Width, Height);
end;

function TGraphTexHelper.UploadTex(Texture: TTexture2d; MipMap: Boolean = True): TGraphTex;
begin
  Result.Width := Texture.Width;
  Result.Height := Texture.Height;
end;

function TGraphTexHelper.UploadTex(Buffer: PScreenBuffer; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2dRaw;
begin
  T := TTexture2dRaw.Create(Buffer);
  Result := Self.UploadTex(TTexture2d(T), MipMap);
  T.Free;
end;

{function TGraphTexHelper.UploadTex(const FileName: TString; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2d;
begin
  if not LoadTexture2d(FileName, T) then begin
    Result.Id := 0;
    Result.Width := 0;
    Result.Height := 0;
  end else begin
    Result := UploadTex(T, MipMap);
    T.Free;
  end;
end;}

function TGraphTexHelper.UploadTex(Data: TData; MipMap: Boolean = True): TGraphTex;
var
  T: TTexture2d;
begin
  if not LoadTexture2d(Data.Stream, T) then begin
    Result.Width := 0;
    Result.Height := 0;
  end else begin
    Result := UploadTex(T, MipMap);
    T.Free;
  end;
  Data.Done;
end;

procedure TGraphTexHelper.FreeTex(const T: TGraphTex);
begin
end;

procedure TGraphTexHelper.BindTex(const T: TGraphTex);
begin
end;

procedure TGraphTexHelper.UnbindTex;
begin
end;

procedure TGraphTexHelper.DrawTex(const T: TGraphTex; const P: TVec2f);
begin
end;

procedure TGraphTexHelper.Tex(const T: TGraphTex; const P: TVec2f);
begin
end;

procedure TGraphTexHelper.DrawTex(const T: TGraphTex; const P, S: TVec2f);
begin
end;

procedure TGraphTexHelper.Tex(const T: TGraphTex; const P, S: TVec2f);
begin
end;

procedure TGraphTexHelper.DrawTex(const T: TGraphTex;
      const P, S: TVec2f;
      Angle: TFloat);
begin
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2f);
begin
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
        const P, S: TVec2f;
		const T, R: TVec2i);
begin
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
      const P, S: TVec2i;
      const T, R: TVec2i;
      Angle: TFloat);
begin
end;

procedure TGraphTexHelper.DrawTex(const Tex: TGraphTex;
    const P, S: TVec2f;
    const T, R: TVec2i;
    Angle: TFloat);
begin
end;

procedure TGraphTexHelper.Tex(const T: TGraphTex;
	const P, Dir: TVec2f;
	const A, B: TVec2i;
	FlipX, FlipY: Boolean);
begin
end;
{$ENDIF}

end.
