@All
I want to write code that will load a bitmap when needed, display it, and then switch to another bitmap as required, and so on.
This should be done in a ReAction window using the bitmap.image class.
Currently, my approach is to create two bitmaps: a user bitmap and a VRAM bitmap. The user bitmap (in RAM) is used for all modifications, and then I blit it to the VRAM bitmap for display.
To achieve this, I created a render() function that takes the number of the bitmap to render.
The entire function looks like this:
void render(num) {
// Free old bitmaps
if (user_bm) {
IGraphics->FreeBitMap(user_bm);
user_bm = NULL;
IDOS->Printf("Freed user_bm\n");
}
if (vram_bm) {
IGraphics->FreeBitMap(vram_bm);
vram_bm = NULL;
IDOS->Printf("Freed vram_bm\n");
}
// Allocate new bitmaps
vram_bm = IGraphics->AllocBitMapTags(width, height, 24,
BMATags_PixelFormat, PIXF_A8R8G8B8,
BMATags_Displayable, TRUE,
TAG_END);
user_bm = IGraphics->AllocBitMapTags(width, height, 24,
BMATags_Friend, vram_bm,
BMATags_UserPrivate, TRUE,
BMATags_PixelFormat, PIXF_A8R8G8B8,
TAG_END);
if (!vram_bm || !user_bm) {
FAIL();
}
// lock bitmap to work with
uint8 *buffer;
uint32 bpr;
APTR lock = IGraphics->LockBitMapTags(user_bm,
LBM_BaseAddress, &buffer,
LBM_BytesPerRow, &bpr,
TAG_END);
if (lock && buffer) {
uint8 *src = pix->samples;
for (int y = 0; y < height; y++) {
uint8 *row = buffer + y * bpr;
for (int x = 0; x < width; x++) {
row[x * 4 + 0] = 255;
row[x * 4 + 1] = src[x * pix->n + 0];
row[x * 4 + 2] = src[x * pix->n + 1];
row[x * 4 + 3] = src[x * pix->n + 2];
}
src += pix->stride;
}
// done, unlock.
IGraphics->UnlockBitMap(lock);
// Copy to vram_bm
int32 blt_result = IGraphics->BltBitMapTags(BLITA_Source, user_bm, BLITA_Dest, vram_bm,
BLITA_Width, width, BLITA_Height, height, TAG_END);
IDOS->Printf("BltBitMapTags result: %ld\n", blt_result);
// Update bitmap.image
IIntuition->SetAttrs(bitmapObj,
BITMAP_BitMap, vram_bm,
BITMAP_Width, width,
BITMAP_Height, height,
TAG_END);
IDOS->Printf("Updated bitmap.image\n");
IIntuition->RefreshWindowFrame(window);
}
Then in the main i do:
int main()
{
......
LockPubScreen();
render();
// Create bitmap gadget
bitmapObj = IIntuition->NewObject(NULL, "bitmap.image",
BITMAP_BitMap, vram_bm,
BITMAP_Width, w,
BITMAP_Height, h,
BITMAP_Screen, pubscreen,
TAG_END);
if (!bitmapObj) {
IDOS->Printf("Failed to create bitmapObj\n");
goto cleanup;
}
.... winobj creationg ...
UnLockPubScreen();
... + main loop in which handle when to call render() again ....
}
So, the first call to render() works perfectly. Everything displays correctly, with no issues. However, on the second call, I often encounter a lockup, either during SetAttrs on the bitmap.image or on RefreshWindowFrame().
When I add more Printf() calls in between, it seems to introduce a delay that allows something to complete, and the lockup sometimes disappears. But when I add more code, the lockups return.
I’m sure I’m missing something critical, like waiting for BltBitMapTags to finish or something similar. It feels like a classic race/timing condition, but I seem to lock/unlock bitmaps when needed, so what’s going wrong? I’m using two bitmaps specifically to avoid unpredictable behavior—doing all the work in the RAM-based bitmap and then blitting to the VRAM bitmap afterward—and yet, it still feels like I’m doing something wrong.
Also, another question: What is the fastest way to display bitmaps on AmigaOS 4 currently? Is BltBitMapTags the best option? Is it accelerated by compositing? If not, should I use compositing instead?
And which approach is better:
Load all data into one large bitmap and navigate through it (but this could be problematic since bitmaps are limited in size, probably 2048x2048 or something like that), or
Load all the data into memory, then create bitmaps each time and blit them as needed? However, constantly creating and freeing bitmaps for every change seems excessive to me.
Thanks for your answers in advance!