Functions of Allegro 4 in Allegro 5 - c

I have a code written in Allegro 4 and am converting it to Allegro 5, but I'm having serious problems with functions that no longer exist in allegro 5, one of them is "blit"
BITMAP *bTile; // Bitmap do tile;
BITMAP *bMapa; // Bitmap do mapa;
BITMAP *bTexturas[20]; // Vetor de bitmap das texturas;
BITMAP *bChar; // Bitmap do personagem;
BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
BITMAP *buffer = create_bitmap(vResolucao_x, vResolucao_y);
bTile = load_bitmap("Tiles/tile.bmp", NULL);
bChar = load_bitmap("Tiles/mario.bmp", NULL);
bMapa = create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = create_bitmap(vTile,vTile);
bMario[1] = create_bitmap(vTile,vTile);
bMario[2] = create_bitmap(vTile,vTile);
blit(bChar, bMario[0], 0, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[1], 33, 0, 0, 0, vTile, vTile);
blit(bChar, bMario[2], 66, 0, 0, 0, vTile, vTile);
// #######################################################
install_int(fGravidade,5);
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
draw_sprite(screen, bMapa, 0, 0 );
while (!key[KEY_ESC]) {
Virtually nothing of this my old code works with Allegro 5, so I'm doing the conversion as I can learn, but this blit function, can not find its like in allegro 5, another function that I can not find your simulate is: install_int (...)

Allegro 5 is essentially a completely new library. Here's a line-by-line translation, as best as can be done. Note that Allegro 5 uses a fundamentally different concept (event loop) and you should really take the time to learn how that works before diving into trying to convert your code.
ALLEGRO_BITMAP *bMario[3];
// ##########################################################
int main()
{
int vResolucao_x = 640;
int vResolucao_y = 480;
init(vResolucao_x, vResolucao_y);
ALLEGRO_BITMAP *buffer = al_create_bitmap(vResolucao_x, vResolucao_y);
bTile = al_load_bitmap("Tiles/tile.bmp");
bChar = al_load_bitmap("Tiles/mario.bmp");
bMapa = al_create_bitmap(vResolucao_x, vResolucao_y);
// ############# - Carrega imagens do mario - ############
bMario[0] = al_create_bitmap(vTile,vTile);
bMario[1] = al_create_bitmap(vTile,vTile);
bMario[2] = al_create_bitmap(vTile,vTile);
al_set_target_bitmap(bMario[0]);
al_draw_bitmap(bchar, 0, 0, 0);
al_set_target_bitmap(bMario[1]);
al_draw_bitmap(bchar, 33, 0, 0);
al_set_target_bitmap(bMario[2]);
al_draw_bitmap(bchar, 66, 0, 0);
al_set_target_backbuffer(display);
// #######################################################
fGravidade = al_create_timer(5 / 1000.0); // ALLEGRO_TIMER*
ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue();
al_register_event_source(queue, al_get_timer_event_source(gfGravidade));
al_register_event_source(queue, al_get_keyboard_event_source());
fCarrega_Sprites_Mapa();
fCarrega_Mapa();
fMostra_Mapa();
al_draw_bitmap(bMapa, 0, 0, 0);
al_flip_display();
while (true) {
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if (event.type == ALLEGRO_EVENT_TIMER) {
// fGravidade ticked
}
else if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
break;
}
}
}

Related

C program using SDL2 only sometimes draws Rect

When I call the following functions:
SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);
SDL_RenderClear(rend);
SDL_SetRenderDrawColor(rend, 100, 255, 80, 255);
SDL_RenderFillRect(rend, &canv);
SDL_RenderDrawRect(rend, &canv);
SDL_RenderPresent(rend);
SDL_Delay(6000);
it only sometimes draws the rectangle, at other times at keeps whatever was at the window location before, or draws the window entirely black. The above functions all return 0.
rend and canv are defined as follows:
Uint32 rend_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Renderer * rend = SDL_CreateRenderer(win, -1, rend_flags);
SDL_Rect canv;
canv.x = 0;
canv.y = 0;
canv.h = 640;
canv.w = 480;
And this is the makefile used:
CC=gcc
CFLAGS=-lSDL2
spectra: spectra.c
$(CC) -o spectra spectra.c $(CFLAGS)
So where did I go wrong, what am I overlooking?

X11 : Cannot draw an image on transparent window created with XCreateWindow

I am trying to create a simple X11 window, which should display a PNG file with transparent areas. I want the window itself to have no (opaque) background, so that the transparent areas in the PNG shows what there is behind the window.
tl;dr I cannot put an image on a semi-transparent window; it gives "Bad Match".
I can successfully create a semi-transparent window using XCreateWindow and XMatchVisualInfo :
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
(Full source code below)
I then create an image using :
// "image32" is a generated image - see source code below
XImage *ximage = XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
And display the image during the Expose event :
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
I compile with gcc test.c -L/usr/X11R6/lib -lX11 -lXrandr -o test and run with ./test :
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 11
Current serial number in output stream: 12
Note : If I replace the lines creating the window (XCreateWindow) with these :
Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
width, height, 1, 0, 0);
It displays a window correctly; however, there is no transparency.
I read the docs about XCreateWindow, XPutImage, XCreateImage and tried playing around with multiple parameters, unsuccessfully.
I have read this SO question and tried playing around with color depth; since the docs mentionned "Bad Match" can be also thrown for incorrect visual, I have checked that the same visual was sent at all places in my code.
Any help is appreciated.
Thanks!
Full source code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// Window size
int height = 256, width = 256;
XImage *CreateTrueColorImage(Display *display, Visual *visual)
{
int i, j;
unsigned char *image32=(unsigned char *)malloc(width*height*4);
unsigned char *p=image32;
for(i=0; i<width; i++)
{
for(j=0; j<height;j++)
{
*p++ = i;
*p++ = i;
*p++ = j;
*p++ = j; // alpha channel (should progressively get transparent towards left)
}
}
// Replacing "DefaultDepth(display,DefaultScreen(display))" with a hardcoded
// 24 or 32 still doesn't work with XCreateWindow. XCreateSimpleWindow works
// with hardcoded 24, but not 32.
return XCreateImage(display, visual, DefaultDepth(display,DefaultScreen(display)),
ZPixmap, 0, image32, width, height, 32, 0);
}
int main(int argc, char **argv)
{
XImage *ximage;
Display *display = XOpenDisplay(NULL);
Visual *visual = DefaultVisual(display, 0);
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(display, DefaultRootWindow(display),
vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80800000; // Red, semi-transparent
//Window window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
// width, height, 1, 0, 0);
Window window = XCreateWindow(display, DefaultRootWindow(display), 0, 0,
width, height, 0, vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel, &attr);
ximage = CreateTrueColorImage(display, vinfo.visual);
XSelectInput(display, window, ButtonPressMask|ExposureMask);
XMapWindow(display, window);
while(1)
{
XEvent event;
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
XPutImage(display, window, DefaultGC(display, 0), ximage,
0, 0, 0, 0, width, height);
break;
case ButtonPress:
exit(0);
}
}
}
I managed to make it work by making two changes.
First, instead of using DefaultGC(display, 0) you should create a GC for your specific window.
GC gc = XCreateGC(display, window, 0, 0);
With that if you hardcode the depth of XCreateImage to 32 it should work correctly.
And you can also use the depth provided by XVisualInfo like so
XCreateImage(display, vinfo.visual, vinfo.depth,
ZPixmap, 0, image32, width, height, 32, 0);

OpenCL - Writing to the Buffer is zero?

I have written a kernel, which should be doing nothing, except from adding an one to each component of a float3:
__kernel void GetCellIndex(__global Particle* particles) {
int globalID = get_global_id(0);
particles[globalID].position.x += 1;
particles[globalID].position.y += 1;
particles[globalID].position.z += 1;
};
with following struct (in the kernel)
typedef struct _Particle
{
cl_float3 position;
}Particle;
my problem is, that when i write my array of particles to the GPU, every component is zero. here is the neccassary code:
(Particle*) particles = new Particle[200];
for (int i = 0; i < 200; i++)
{
particles[i].position.x = 5f;
}
cl_Particles = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err);
if (err != 0)
{
std::cout << "CreateBuffer does not work!" << std::endl;
system("Pause");
}
clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, &particles, 0, NULL, NULL);
//init of kernel etc.
err = clSetKernelArg(kernel, 0, sizeof(Particle) * 200, &cl_Particles);
if (err != 0) {
std::cout << "Error: setKernelArg 0 does not work!" << std::endl;
system("Pause");
}
and this is my struct on the CPU:
typedef struct _Particle
{
cl_float4 position;
}Particle;
can someone help me with this problem?
(any clue is worth to discuss...)
Thanks
Your code snippet contains some typical C programming errors. At first,
(Particle*) particles = new Particle[200];
does not declare a new variable particle as a pointer to Particle. It must be:
Particle *particles = new Particle[200];
As next, in your call of
clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, &particles, 0, NULL, NULL);
you passed a pointer to the particles pointer as the 6th parameter (ptr). But, here you must pass a pointer to the region on the host containing the data. Thus, change &particles to particles:
clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, 0, NULL, NULL);
The setup of the kernel arguments is also wrong. Here, you must pass the OpenCL buffer created with clCreateBuffer. Thus, replace
err = clSetKernelArg(kernel, 0, sizeof(Particle) * 200, &cl_Particles);
with:
err = clSetKernelArg(kernel, 0, sizeof(cl_Particle), &cl_Particles);
As clCreateBuffer returns a value of type cl_mem, the expression sizeof(cl_Particle) evaluates to the same as sizeof(cl_mem). I recommend to always call sizeof() on the variable, so you need to change the data-type only in one place: the variable declaration.
On my platform, cl_float3 is the same as cl_float4. This might not be true on your/every platform, so you should always use the same type in the host code and in the kernel code. Also, in your kernel code you should/must use the type float4 instead of cl_float4.
I hope, I got the C calls right because I actually tested it with this C++ code. This code snippet contains the fixed C calls as comments:
Particle *particles = new Particle[200];
for (int i = 0; i < 200; i++)
{
//particles[i].position.x = 5f;
particles[i].position.s[0] = 0x5f; // due to VC++ compiler
}
//cl_mem cl_Particles = cl_createBuffer(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err); // FIXED
cl::Buffer cl_Particles(context, CL_MEM_READ_WRITE, sizeof(Particle)*200, NULL, &err);
checkErr(err, "Buffer::Buffer()");
//err = clEnqueueWriteBuffer(queue, cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, 0, NULL, NULL); // FIXED
queue.enqueueWriteBuffer(cl_Particles, CL_TRUE, 0, sizeof(Particle) * 200, particles, NULL, NULL);
checkErr(err, "ComamndQueue::enqueueWriteBuffer()");
//init of kernel
cl::Kernel kernel(program, "GetCellIndex", &err);
checkErr(err, "Kernel::Kernel()");
//err = clSetKernelArg(kernel, 0, sizeof(cl_Particle), &cl_Particles); // FIXED
err = kernel.setArg(0, sizeof(cl_Particles), &cl_Particles);
checkErr(err, "Kernel::setArg()");

Serial port, WriteFile affects ReadFile

I'm having a problem with the serial port code.
I just do:
opencomm();
send();
closecomm();
and the ClearCommError() (inside recv()) returns in
comstat.cbInQue the same amount that was sent.
So, if sizeof (sendbuff) is 100,
I get 100 in comstat.cbInQue.
After reading one byte with ReadFile, comstat.cbInQue decrements (after subsequent ClearCommError(), of course).
The values read are not the ones that were written.
There is no device connected to the port.
The strangest thing is this code used to work, but not anymore.
WORD sendbuff[128];
static HANDLE hComm;
static void opencomm (void)
{
static COMMTIMEOUTS timeouts = {0,0,0,0,0};
static DCB dcb = {
sizeof (DCB), // DCBlength
115200, // * BaudRate
1, // fBinary
0, // * fParity
0, // fOutxCtsFlow
0, // fOutxDsrFlow
0, // fDtrControl
0, // fDsrSensitivity
1, // fTXContinueOnXoff
0, // fOutX
0, // fInX
0, // fErrorChar
0, // fNull
0, // fRtsControl
0, // fAbortOnError
0, // fDummy2
0, // wReserved
8*k, // XonLim
2*k, // XoffLim
8, // * ByteSize
0, // * Parity
0, // * StopBits
0, // XonChar
1, // XoffChar
0, // ErrorChar
0, // EofChar
0, // EvtChar
0 // wReserved1
};
hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hComm != INVALID_HANDLE_VALUE) {
SetupComm(hComm, 16*k, 16*k);
SetCommState(hComm, &dcb);
SetCommTimeouts(hComm, &timeouts);
}
}
static void closecomm (void)
{
CloseHandle(hComm);
}
static BYTE recv (void)
{
BYTE text;
DWORD temp;
COMSTAT comstat;
while (1) {
ClearCommError(hComm, &temp, &comstat);
if (comstat.cbInQue != 0) break;
Sleep(1);
}
ReadFile(hComm, &text, 1, &temp, NULL);
return text;
}
static void send (void)
{
DWORD temp;
// send to other comp
WriteFile(hComm, sendbuff, sizeof (sendbuff), &temp, NULL);
// check other comp done
if (recv() != 0xAA) {
Beep(1000, 100);
quit(); // comm error
}
}
It was the cable. Not properly shielded and too long.

How to upload 32 bit image to server-side pixmap

I'm trying to create server-side RGBA pixmap from client side buffer. CreatePixmap & CreateImage work ok for 32 and 24 bit, but XPutImage result in Match Error returned by server
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage)
Serial number of failed request: 8
Current serial number in output stream: 8
server does support 32 bit pixmaps (xdpyinfo output: https://gist.github.com/2582961). Same behaviour on ubuntu 12.04 (X.Org version: 1.11.3) and OSX with X.app (X.Org version: 1.10.3)
Why following code fails?
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
int width = 100;
int height = 100;
int depth = 32; // works fine with depth = 24
int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
Display *display=XOpenDisplay(0);
unsigned char *image32=(unsigned char *)malloc(width*height*4);
XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
XPutImage(display, p, DefaultGC(display, 0), img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
XEvent ev;
while (1) {
XNextEvent(display, &ev);
}
}
Update: It looks like I finally got answer: use GC associated with pixmap instead of DefaultGC (which has depth of root window)
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
int width = 100;
int height = 100;
int depth = 32; // works fine with depth = 24
int bitmap_pad = 32; // 32 for 24 and 32 bpp, 16, for 15&16
int bytes_per_line = 0; // number of bytes in the client image between the start of one scanline and the start of the next
Display *display=XOpenDisplay(0);
unsigned char *image32=(unsigned char *)malloc(width*height*4);
XImage *img = XCreateImage(display, CopyFromParent, depth, ZPixmap, 0, image32, width, height, bitmap_pad, bytes_per_line);
Pixmap p = XCreatePixmap(display, XDefaultRootWindow(display), width, height, depth);
XGCValues gcvalues;
GC gc = XCreateGC(display, p, 0, &gcvalues);
XPutImage(display, p, gc, img, 0, 0, 0, 0, width, height); // 0, 0, 0, 0 are src x,y and dst x,y
XEvent ev;
while (1) {
XNextEvent(display, &ev);
}
}
The problem is with DefaultGC() which return a GC with bit depth of system default screen. If you look at line 53 of your gist paste you see that this is 24:
depth of root window: 24 planes
On line 63 you see that it uses 0x22 as default which is shown in more detail in line 64 to 70:
visual:
visual id: 0x22
class: TrueColor
depth: 24 planes
available colormap entries: 256 per subfield
red, green, blue masks: 0xff0000, 0xff00, 0xff
significant bits in color specification: 8 bits
You could probably do this a bit nicer but as a start you can try this:
Note: This uses system visuals so most probably only support depth of 24 or 32.
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef DEBUG
int dbg = 1;
#else
int dbg = 0;
#endif
/* Return a GC based on depth */
int gc_depth(int depth, Display *dpy, Window scr, Window root, GC *gc)
{
Window win;
Visual *visual;
XVisualInfo vis_info;
XSetWindowAttributes win_attr;
unsigned long win_mask;
if(!XMatchVisualInfo(dpy, scr, depth, TrueColor, &vis_info)) {
fprintf(stderr,
" * ERR: %d depth not supported\n",
depth
);
return 1;
}
visual = vis_info.visual;
win_attr.colormap = XCreateColormap(dpy, root, visual, AllocNone);
win_attr.background_pixel = 0;
win_attr.border_pixel = 0;
win_mask = CWBackPixel | CWColormap | CWBorderPixel;
win = XCreateWindow(
dpy, root,
0, 0,
100, 100, /* dummy size */
0, depth,
InputOutput, visual,
win_mask, &win_attr);
/* To flush out any errors */
if (dbg) XSync(dpy, True);
*gc = XCreateGC(dpy, win, 0, 0);
if (dbg) XSync(dpy, True);
XDestroyWindow(dpy, win);
if (dbg) XSync(dpy, True);
return 0;
}
int main(void)
{
int w = 100;
int h = 100;
int depth = 32;
int bitmap_pad = 32;
int bpl = 0;
Display *dpy;
Window root;
Window scr;
GC gc;
int root_depth;
Pixmap pm;
XImage *img;
unsigned char *buf_img;
if(!(dpy = XOpenDisplay(NULL))) {
fprintf(stderr,
" * ERR: Failed to open display.\n");
return 1;
}
#ifdef DEBUG
/* To get errors in order, slows down
* One can also define int _Xdebug = 1;
* */
XSynchronize(dpy, True);
#endif
root = XDefaultRootWindow(dpy);
scr = XDefaultScreen(dpy);
if ((buf_img = malloc(w * h * 4)) == NULL) {
fprintf(stderr,
" * ERR: Unable to alloacte %d bytes\n",
w * h * 4);
return 1;
}
root_depth = DefaultDepth(dpy, scr);
fprintf(stderr,
"Default depth: %d\n",
root_depth);
/* This should be doen more nice */
if (depth != root_depth) {
if (gc_depth(depth, dpy, scr, root, &gc) != 0)
return 1;
} else {
gc = DefaultGC(dpy, 0);
}
img = XCreateImage(
dpy, CopyFromParent,
depth, ZPixmap,
0, (char *)buf_img,
w, h,
bitmap_pad, bpl);
/* To flush out any errors */
if (dbg) XSync(dpy, True);
pm = XCreatePixmap(
dpy, root,
w, h,
depth);
if (dbg) XSync(dpy, True);
XPutImage(
dpy, pm,
gc, img,
0, 0,
0, 0,
w, h);
if (dbg) XSync(dpy, True);
XFreePixmap(dpy, pm);
XDestroyImage(img);
XFreeGC(dpy, gc);
if (dbg) XSync(dpy, True);
fprintf(stderr,
"OK!\n");
return 0;
}
Well, your code works for 32 bits images if you just create a GC passing a drawable on argument which is 32 bits. XCreateGC(dpy, drawable, 0, 0), where drawable can be a pixmap with 32 bits depth. It works perfect with me.

Resources