Page 1 of 1

wxWidgets and Allegro (gfx library)

Posted: Fri Oct 01, 2010 1:06 pm
by rayburgemeestre
This is a demo as to how to combine my two favorite libraries wxWidgets and Allegro. I've tested this using Allegro 4.2.3 and wxWidgets 2.8.11.

Reasons for using Allegro for your wx application gfx

- graphics are a lot faster than when you'd use wx equivalent functions.
- easy to add AllegroGL (it's just one include after allegro.h) to add OpenGL hardware acceleration, and there are tons of other extensions for Allegro.
- allegro has a very clean and well documented manual/API.
- allegro is also multi-platform, although I've only tested this on windows.

Sample project

Attached is a sample project with two wxStaticBitmap controls. I've included the source, Visual Studio 2010 and DialogBlocks project files, could not include the binaries (attachment was not allowed due to filesize). I used DialogBlocks for my wxWidgets stuff. This code also works with the DigitalMars Compiler, mingw, WATCOM, all tested under Windows. Maybe I will upload binary later to my website and post the URL.

I use the OnCreate() event to initialize allegro, and OnIdle() to start rendering the next frame. You might not need continuous redrawing, but in my demo I created a silly animation on one canvas (wxStaticBitmapCanvas), but another smaller canvas (wxStaticBitmapSmallCanvas) is only redrawn when necessary.

I made that animation a little bit interactive with the mouse to demonstrate how you can use the mouse on the canvas, etc.

Image

The required code summarized

Include allegro first like this.

Code: Select all

#define ALLEGRO_NO_MAGIC_MAIN
#define RGB AL_RGB
#include <allegro.h>
#include <winalleg.h>
#undef RGB
In OnCreate() of your window, or in some other appropriate place, Initialize allegro.

Code: Select all

install_allegro(SYSTEM_NONE, &errno, NULL);
set_palette(desktop_palette); // example
set_color_depth(32); // example
In your canvas' OnPaint() event, draw your allegro "BITMAP *" to the canvas.

Code: Select all

wxPaintDC dc(wxDynamicCast(event.GetEventObject(), wxWindow)); // you probably already have the wxPaintDC

// Found the following code by searching for a very long time in the wxWidgets source code ;)
WXHDC wxHDC = wxPaintDC::FindDCInCache((wxWindow*) event.GetEventObject());
HDC hDC = (HDC) wxHDC;

... // do your thing here 

draw_to_hdc(hDC, allegroBitmap, 0, 0); // where allegroBitmap is a valid "BITMAP *"
Feedback

I'd really appreciate a reply if this was useful for you, I'm also curious if there's anybody else using allegro combined with wxWidgets.
Also feedback on my C++ code is greatly appreciated, like if I could use std::vector more efficiently I'd like to know how.

Re: wxWidgets and Allegro (gfx library)

Posted: Sat Feb 20, 2016 9:27 pm
by jperez
Hi, I tried to use it with the Allegro 5 but that function seems to be deprecated, but i found another way using wxWidgets 3.1 and Allegro 5.1 through an wxMemoryInputStream object.
The idea is to store the rendered Allegro bitmap to a memory file using the allegro function al_open_memfile and then using memcpy to send it to a raw buffer and then reading it in a wxMemoryInputStream object, then it can be converted to an wxImage and later used as a wxBitmap.

I modified a function written in this forum:
https://www.allegro.cc/forums/thread/614260
I modified it like this:

Code: Select all

bool MainFrame::SaveBitmap(ALLEGRO_BITMAP * sub, int x, int y, int slice_w, int slice_h, const char * prefix, wxBitmap &returnBitmap)
{
  int size;
  void * buffer;
  int real_size;
  ALLEGRO_FILE * memfile;
  if(!sub)
  {
    return false;
  }
  /* Allocate a buffer that should always be too big.*/
  size = slice_w * slice_h * 4 * 2;
  buffer = calloc(size, 1);
  real_size = 0; if (!buffer)
  {
    fprintf(stderr, "Couldn't allocate the buffer!\n");
    return false;
  }
  /* Open memfile. */
  memfile = al_open_memfile(buffer, size, "rw");
  if (!memfile)
  {
    fprintf(stderr, "Failed to open memfile!\n");
  }
  else
  {
    /* save the bitmap into the memfile. */
    al_save_bitmap_f(memfile, ".bmp", sub);
    /* Get the real size of the bitmap. */
    real_size = al_ftell(memfile);
    if (real_size < 1)
    {
      fprintf(stderr, "Real size is too small!\n");
    }
    else
    {
      /* now, buffer contains the correct bitmap data. Save that to a file
      * (but if could be stored into sqlite as well, if needed).
      */
      wxMemoryInputStream inputStream((void*)buffer, size);
      wxImage image(inputStream, wxBITMAP_TYPE_BMP);
      returnBitmap = wxBitmap(image);
    }
    al_fclose(memfile);
  }
  free(buffer);
};
Right now i used it like this:

Code: Select all

  ALLEGRO_BITMAP *myBuffer = al_create_bitmap(256, 256);
  al_set_target_bitmap(myBuffer);

  for (int row = 0; row < 256; row++)
  {
    for (int column = 0; column < 256; column++)
    {
      al_put_pixel(column, row, al_map_rgb(column, row, 128));
    }//end loop row
  }//end loop on column

  wxBitmap myBitmap;
  SaveBitmap(myBuffer, 0, 0, 256, 256, "bmp", myBitmap);

  wxStaticBitmap *myStaticBitmap = new wxStaticBitmap(this, wxID_ANY, myBitmap, wxPoint(0, 0), wxSize(256, 256), 0);
  mainSizer->Add(myStaticBitmap, 0, wxALL, 5);

  al_destroy_bitmap(myBuffer);
  
It's working for me in Ms-Windows7 x64 and now I am trying to create a canvas-like object for use in a transparent window and this canvas could draw the controls.