Results 1 to 6 of 6

Thread: Showing a pSDL_SURFACE on TCanvas on form?

  1. #1

    Showing a pSDL_SURFACE on TCanvas on form?

    Hello again,

    is there a way to display a pSDL_SURFACE on a form? Basically I am trying to build a level editor and since I already have a lot of code using SDL I wish to use that in combination with the convience of the components and form designer.

    So basically I have been messing around using the below code. Basically I am looping through each pixel and trying to set the pixel of the TCanvas of the form. Now, I have two problems with this:
    1. It is extremely slow when resizing the form.
    2. It doesn't work, see attachment. The surface should be a black background with a red rectangle but instead displays as a collection of red, green and blue pixels.

    Code:
    unit Unit1;
    
    {$mode objfpc}{$H+}
    
    interface
    
    uses
      Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, SDL, Unit2;
    
    type
    
      { TForm1 }
    
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormPaint(Sender: TObject);
      private
        { private declarations }
      public
        { public declarations }
      end;
    
    var
      Form1: TForm1;
      MapDisplay: pSDL_SURFACE;
    
    implementation
    
    {$R *.lfm}
    
    { TForm1 }
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      Rect: pSDL_RECT;
    begin
      SDL_INIT(SDL_INIT_VIDEO);
      MapDisplay:= SDL.SDL_CreateRGBSurface(SDL_SWSURFACE, 499, 500, 32, 255, 255, 255, 0);
      SDL_FillRect(MapDisplay, NIL, $000000);
      New(Rect);
      Rect^.x:= 5;
      Rect^.y:= 100;
      rect^.w:= 50;
      Rect^.h:= 20;
      SDL_FillRect(MapDisplay, NIL, $00FF00);
      Dispose(Rect);
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      SDL_FreeSurface(MapDisplay);
    end;
    
    // here I have the actual rendering code.
    procedure TForm1.FormPaint(Sender: TObject);
    var
      I, J: integer;
      Loc: ^LongWord;
    begin
      For I:= 0 To MapDisplay^.w -1 Do
        For J:= 0 To MapDisplay^.h -1 Do
          begin
            Loc:= MapDisplay^.pixels + I + J*MapDisplay^.w;
            Canvas.Pixels[I,J]:= Loc^;
          end;
    end;
    
    end.
    So I am kinda lost, and would like to know what I am doing wrong and even if there is a better more efficient way of doing this.

    Thanks.

    Example.jpg

  2. #2
    If worrying about slowness, this is the cause:
    Code:
    Canvas.Pixels[I,J]:= Loc^;
    Using Canvas functions to draw is always slow. Since you started making SDL screen, you could look into drawing with SDL too.

    When drawing on a form canvas, and then moving window outside of screen and back, all drawn graphics disappear. With no SDL or other graphics API this is fixed by drawing on TImage.Picture.Bitmap.Canvas. You don't need to handle onPaint event then, because you can be sure that what you draw once will remain forever.

  3. #3
    Frankly, I think it will be easier to do all the drawing in SDL and just have your editor work with two separate windows, the SDL-rendered one and the form-designer one. Just create a timer on the form to periodically check for SDL events and update the display surface if necessary, and that's pretty much all. You could, eventually, go with having all SDL-related stuff handled in a thread, but, in my own experience, that's too much of a complication in exchange for very little benefit.

  4. #4
    Doesent SDL_CreateWindowFrom alows you to use existing GUI window to render SDL content to so you don't have to create a new SDL window?

  5. #5
    It is possible in SDL2. Glancing at the code, I think T-Bear is using SDL1, which does not allow that. Maybe with some awful hacking.

  6. #6

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Comodo SSL