Hi all, something to note here. If you create your own image buffer, you should be aware of something that will cause imagedestroy to fail hard if you don't match the behaviour.
FB's imagecreate aims to be paragraph aligned (aligned to 16 bytes). This is for people who wish to use fast SSE commands on their buffer. So what FB does, is it allocates a bit more than needed. It stores the original pointer as a temporary. It then returns to the user the next address within the buffer that is correctly aligned. It stores the real pointer taken from malloc just before this aligned address.
So, if you try and pass a custom buffer to imagedestroy that is not aware of this, it will try to do dellocate(cast(any ptr ptr, p)[-1]) and probably crash, and not free the memory. You could just use your own version of imagedestroy too if you liked, that would probably be fine.
Here's an attempt I made, using the details from the gfx_image.c
Code: Select all
/'
function ImgCreate (byval PicWidth as uinteger = 0, byval PicHeight as uinteger = 0) as any ptr
dim as uinteger ptr Pic
dim as uinteger PicEmpty = 0
dim as integer PicBpp = 4
dim as uinteger PicVersion = 7
dim as uinteger PicPitch = ((PicWidth*PicBpp) + &hF) and not &hF
dim as uinteger PicSize = PicPitch*PicHeight
Pic = allocate((32+PicSize)*sizeof(ubyte))
Pic[0] = PicVersion: Pic[1] = PicBpp
Pic[2] = PicWidth: Pic[3] = PicHeight
Pic[4] = PicPitch: Pic[5] = PicEmpty
Pic[6] = PicEmpty: Pic[7] = PicEmpty
for k as uinteger = 1 to PicSize\4
Pic[7+k] = rgba(255,0,255,0)
next k
return Pic
end function
'/
function ImgCreate (byval PicWidth as uinteger = 0, byval PicHeight as uinteger = 0) as any ptr
dim as any ptr Pic
dim as uinteger PicEmpty = 0
dim as integer PicBpp = 4
dim as uinteger PicVersion = 7
dim as uinteger PicPitch = ((PicWidth*PicBpp) + &hF) and not &hF
dim as uinteger PicSize = PicPitch*PicHeight
' Here are some smelly lines to do the alignment of the buffer and
' the top secret hidden original pointer magic. I hope I got them
' correct
' 0xF for the para alignment, p_size is sizeof(void *) rounded up to % 16 for the storage for the original pointer
dim as integer p_size = (sizeof(any ptr) + &HF) and &HF
dim as any ptr tmp = allocate(PicSize + 32 + p_size + &HF)
' Awooga, Awooga, sound the alarms, I just cast this to a uinteger
' to do the pointer math, this will cause a 64 bit system to LITERALLY EXPLODE
' and maybe even worse. But FBC isn't on 64 bit yet anyway.
Pic = cast(any ptr, (cast(uinteger, tmp) + p_size + &HF) and not &HF)
cast(any ptr ptr, Pic)[-1] = tmp
' Phew, I'm glad that's over
dim as uinteger ptr hdr = cast(uinteger ptr, Pic)
hdr[0] = PicVersion : hdr[1] = PicBpp
hdr[2] = PicWidth : hdr[3] = PicHeight
hdr[4] = PicPitch : hdr[5] = PicEmpty
hdr[6] = PicEmpty : hdr[7] = PicEmpty
return Pic
end function
screenres 640, 480, 32
dim as any ptr img = ImgCreate(640, 480)
for i as integer = 0 to 9999
pset img, (int(rnd() * 640), int(rnd() * 480)), int(rnd()*16777216)
next i
put(0, 0), img, PSET
imagedestroy(img)
sleep