Menu

Request: TAd2DBitmapTexture - LoadFromMemory

General
2008-12-22
2013-05-14
  • Nobody/Anonymous

    This is my request, in TAd2DBitmapTexture can you add a procedure to load directly from memory?
    We could skip one step to copy a block of memory (usually using TAd2dBitmap as Raw proxy). This is usefull & more fast to load a texture directly from our defined raw buffer, without need copy it to TAd2dBitmap first. Especially to load video buffer as dynamic texture.
    I have modify the code (currently in OpenGL driver), each time I update from CVS I must edit the new code to make it fit of my need. Can you add this to CVS version?

    abstract class:

    TAd2DBitmapTexture = class(...)
    public
      ...
    procedure LoadFromMemory(const Src: Pointer; const AWidth, AHeight: Integer; const ABitDepth: TAdBitDepth); virtual; abstract;
    ...
    end;

    OpenGL:

    // this procedure copied from LoadFromBitmap and modify some variable to fit the requirements.

    procedure TOGLBitmapTexture.LoadFromMemory(const Src: Pointer; const AWidth,
      AHeight: Integer; const ABitDepth: TAdBitDepth);
    var
      mem:PByte;
      w,h,x,y:integer;
      pnt32:PRGBARec;
      cur16:PWord;
      cur32:PLongWord;
      newtex: boolean;
    begin
      //Calculate power of two size of the texture
      w := 1 shl ceil(log2(AWidth));
      h := 1 shl ceil(log2(AHeight));

      //Decide whether a new texture object has to be created
      if (w <> FWidth) or (h <> FHeight) or
         (ABitDepth <> FBitDepth) or (not Loaded) then
      begin
        FlushTexture;
        new(PCardinal(FTexture));
        glGenTextures(1,FTexture);
        newtex := true;
      end else
        newtex := false;

      //Bind the current texture
      glBindTexture(GL_TEXTURE_2D, PCardinal(FTexture)^);

      //Set some properties
      FWidth := w;
      FHeight := h;
      FBitDepth := ABitDepth;
      FBaseWidth := AWidth;
      FBaseHeight := AHeight;
      FHasMipMap := false;

      //Reserve memory for storing the texture data 
      GetMem(mem,w *h * Ord(ABitDepth) div 8);
     
      try
        if ABitDepth = ad32Bit then
        begin
          if newtex or FParent.FMipmaps then
          begin
            cur32 := PLongWord(mem);
            pnt32 := Src;
            for y := 0 to AHeight - 1 do
            begin
              Move(pnt32^, cur32^, AWidth * 4);
              inc(pnt32, AWidth);
              inc(cur32, w);
            end;
          end;

          if FParent.FMipmaps then
          begin
            FHasMipMap := true;
            gluBuild2DMipmaps(GL_TEXTURE_2D, 4, w, h, GL_BGRA, GL_UNSIGNED_BYTE, mem)
          end
          else
          begin
            if newtex then
            begin
              glTexImage2D(
                GL_TEXTURE_2D, 0, GL_RGBA,
                w, h,
                0, GL_BGRA, GL_UNSIGNED_BYTE, mem);
            end else
            begin
              glTexSubImage2D(
                GL_TEXTURE_2D, 0,
                0, 0, BaseWidth, BaseHeight,
                GL_BGRA, GL_UNSIGNED_BYTE, Src)
            end;
          end;
        end
        else
        begin
          cur16 := PWord(mem);
          pnt32 := Src;
          for y := 0 to AHeight - 1 do
          begin
            for x := 0 to w - 1 do
            begin
              if (x < AWidth) then
              begin
                cur16^ := ABGRTo16Bit(pnt32^.a,pnt32^.b,pnt32^.g,pnt32^.r);
                inc(pnt32);
              end;
              inc(cur16);
            end;
          end;

          glTexImage2D(    GL_TEXTURE_2D, 0, GL_RGBA16, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, mem);
        end;

      finally
        FreeMem(mem,w*h* Ord(ABitDepth) div 8);
      end;
    end;

    // we still can use LoadFromMemory to load from TAd2dBitmap

    procedure TOGLBitmapTexture.LoadFromBitmap(ABmp: TAd2dBitmap; ABitDepth: TAdBitDepth);
    begin
      LoadFromMemory(ABmp.ScanLine, ABmp.Width, ABmp.Height, ABitDepth);
    end;

    Thanks!

     
    • Andreas Stöckel

      Hello,

      thank you for your suggestion. Actually I didn't implement it as you did, because I want the plugin interface to be as lightweight as possible.

      I simply added a class TAd2DMemoryBitmap that is derived from the new TAd2DCustomBitmap class. TAd2DMemoryBitmap requests the memory and the width and the height of the bitmap in the constructor.

      Here is an example:

      adbmp := TAd2DMemoryBitmap.Create(buf.Memory, buf.Width, buf.Height);
      FTexture.LoadFromBitmap(adbmp, ad32Bit);
      adbmp.Free;

      I used the new class in the video module, what makes it really faster (especially with HD-Videos).

      So thank you again,
      Andreas

       
    • Nobody/Anonymous

      Wooha... that's the point!

      Updating from CVS... done!

      Looking for the changes...
      - There are many changes :)
      - 2 classes added in AdBitmapClass.pas --> You rock dude!
      - Looking other change(s) ... :D

      >> Actually I didn't implement it as you did, because I want the plugin interface to be as lightweight as >> possible.

      Brilliant!, the plugin interface keep simplicity.
      Actually, I have the same idea previously, but considering we still need create a new DirectBitmapBuffer object to do the same job (need some a times to create the object in Delphi). But I 100% agree with you, that was the wise one ;)

      Great and thanks again!

       
    • Nobody/Anonymous

      Can I ask which video library you use to get a plain video pixel buffer?
      Do you have a simple demo to show how it works.
      thx.

       
    • Andreas Stöckel

      I'm using Acinerella. See http://acinerella.sourceforge.net/ there's a demo included.

       
    • akini

      akini - 2009-01-12

      Thx,  I downloaded acinerella and compiled delphi module. Tried several video files but audio did not work. Maybe its each developer should compile own acinerella.dll FFMPEG binary. I don't have a working C compiler system (or lack of C/C++ toolset skills).

      No wait..., acinerella_demo.exe was writing audio to a out.wav file instead of the audio device :-)

      I do have some .wmv files with WMAPro3 audio track but those does not work in an acinerella.dll (precomiled static ffmpeg binary). No suprise  really, WMAPro3 seems to be a problem for opensource projects.

      Would you willing to post a 3d texture example with audio playback playber?

       
    • Andreas Stöckel

       

Log in to post a comment.