#!/usr/bin/perl

use 5.14.1;             # tested with 5.10.1, 5.12.4, 5.14.1 under Linux/amd64 (debian squeeze), also Strawberry Perl 5.12.3 on WinXP (32bit)
                        # Alien::SDL build from source + all prereq ( usually last choice on running build script ) version 1.428
                        # SDL version 2.533

use Inline with => 'SDL';
no strict;
use Inline C;
use strict;


use SDL::Event;
use SDL::Surface;
use SDLx::App;
use SDLx::Layer;
use SDLx::LayerManager;
use SDL::Image;


#my $app = SDLx::App->new(t => 'memleaks', w => 640, h => 480, flags => SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL);
my $app = SDLx::App->new(t => 'memleaks', w => 640, h => 480, flags => SDL_SWSURFACE);  # SW or HW surface dosent matter, the leaking is the same

my $button1 = SDL::Image::load('login_button.png');
my $button2 = SDL::Image::load('login_button_hover.png');

my $layer1 = SDLx::Layer->new($button1, 100, 100);
my $layer2 = SDLx::Layer->new($button2, 110, 110);

my $layers = SDLx::LayerManager->new();

my $surface1 = $layer1->surface;
my $surface2 = $layer2->surface;

my $rect1    = $layer1->clip;
my $rect2    = $layer2->clip;

my $pos1    = $layer1->pos;
my $pos2    = $layer2->pos;


$layers->add($layer1);
$layers->add($layer2);

sub event_handler{
    my ($event, $app) = @_;
    if($event->type == SDL_QUIT) {
        $app->stop;
    }
}
$app->add_event_handler( \&event_handler );




# example #1
sub show_handler_1{
    my($delta, $screen) = @_;
    
    $layers->blit($screen); # this leaks some memory
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_1 );


# example #2
sub show_handler_2{
    my($delta, $screen) = @_;
    
    for my $layer(@{$layers->layers}){
        SDL::Video::blit_surface( $layer->surface, $layer->clip, $screen->surface, $layer->pos );  # this also leaks (even more) memory
    }
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_2 );


# example #3
sub show_handler_3{
    my($delta, $screen) = @_;
    
    for my $layer(@{$layers->layers}){
        native_blit($layer->surface, $layer->pos->x, $layer->pos->y, $screen);   # the same
    }
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_3 );


# example #4
sub show_handler_4{
    my($delta, $screen) = @_;
    
    for my $layer(@{$layers->layers}){ # this is ok... but,
        $layer->surface;    # in fact even this leaks
        $layer->pos->x;     # also this
        $layer->clip;       # and this
    }
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_4);


# example #5
sub show_handler_5{
    my($delta, $screen) = @_;
    
     native_blit($surface1, 100, 100, $screen);   # this finally works
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_5 );



# example #6
sub show_handler_6{
    my($delta, $screen) = @_;
    
    SDL::Video::blit_surface( $surface1, $rect1, $screen->surface, $pos1 ); # this also works
    SDL::Video::blit_surface( $surface2, $rect2, $screen->surface, $pos2 );
    
    $screen->flip();    
}
#$app->add_show_handler( \&show_handler_6 );




$app->run();



__END__
__C__

void native_blit(SDL_Surface *layer, Sint16 x, Sint16 y, SDL_Surface *screen){

    SDL_Rect dest_rect = {x, y, 0, 0 };
    SDL_Rect *drect_p;
    drect_p =& dest_rect;
    
    if(SDL_MUSTLOCK(screen))
        if(SDL_LockSurface(screen) < 0)
            return;      

    SDL_BlitSurface(layer, NULL, screen, drect_p);

    if (SDL_MUSTLOCK(screen))
           SDL_UnlockSurface(screen);

    drect_p = NULL;
}
