PDA

View Full Version : Showing a pSDL_SURFACE on TCanvas on form?



T-Bear
24-06-2014, 12:19 PM
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:

It is extremely slow when resizing the form.
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.



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.

1299

User137
24-06-2014, 01:36 PM
If worrying about slowness, this is the cause:

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.

Super Vegeta
24-06-2014, 08:13 PM
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.

SilverWarior
24-06-2014, 09:55 PM
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?

Super Vegeta
25-06-2014, 06:13 AM
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.

paul_nicholls
25-06-2014, 11:50 PM
@T-Bear: maybe this can help?
http://www.pascalgamedevelopment.com/showthread.php?4926-SDL-graphics-Delphi-forms

cheers,
Paul