/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * QNX Photon bitmap management routines. * * By Eric Botcazou. * * See readme.txt for copyright information. */ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintqnx.h" #ifndef ALLEGRO_QNX #error Something is wrong with the makefile #endif /* this bitmap is guaranteed to point to the visible contents */ BITMAP *ph_frontbuffer; /* we may have to recycle the screen surface as a video bitmap, * in order to be consistent with how other platforms behave */ static int reused_screen = FALSE; #ifdef ALLEGRO_NO_ASM /* ph_write_line: * Line switcher for video bitmaps. */ unsigned long phd_write_line(BITMAP *bmp, int line) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; PgWaitHWIdle(); } return (unsigned long)(bmp->line[line]); } /* ph_unwrite_line: * Line updater for video bitmaps. */ void ph_unwrite_line(BITMAP *bmp) { if (bmp->id & BMP_ID_AUTOLOCK) { bmp->id &= ~(BMP_ID_LOCKED | BMP_ID_AUTOLOCK); } } #endif /* ph_acquire: * Bitmap locking for video bitmaps. */ void ph_acquire(BITMAP *bmp) { if (!(bmp->id & BMP_ID_LOCKED)) { bmp->id |= BMP_ID_LOCKED; PgWaitHWIdle(); } } /* ph_release: * Bitmap unlocking for video bitmaps. */ void ph_release(BITMAP *bmp) { bmp->id &= ~BMP_ID_LOCKED; } /* _make_video_bitmap: * Helper function for wrapping up video memory in a video bitmap. */ static BITMAP *_make_video_bitmap(int w, int h, unsigned long addr, struct GFX_VTABLE *vtable, int bpl) { int i, size; BITMAP *b; if (!vtable) return NULL; size = sizeof(BITMAP) + sizeof(char *) * h; b = (BITMAP *) malloc(size); if (!b) return NULL; b->w = b->cr = w; b->h = b->cb = h; b->clip = TRUE; b->cl = b->ct = 0; b->vtable = vtable; b->write_bank = b->read_bank = _stub_bank_switch; b->dat = NULL; b->id = BMP_ID_VIDEO; b->extra = NULL; b->x_ofs = 0; b->y_ofs = 0; b->seg = _video_ds(); b->line[0] = (char *)addr; for (i = 1; i < h; i++) b->line[i] = b->line[i - 1] + bpl; return b; } /* make_photon_bitmap: * Connects a Photon context with an Allegro bitmap. */ BITMAP *make_photon_bitmap(PdOffscreenContext_t *context, int w, int h, int id) { struct BITMAP *bmp; char *addr; addr = PdGetOffscreenContextPtr(context); if (!addr) return NULL; /* create Allegro bitmap */ bmp = _make_video_bitmap(w, h, (unsigned long)addr, &_screen_vtable, context->pitch); if (!bmp) return NULL; bmp->id = id; #ifdef ALLEGRO_NO_ASM bmp->write_bank = ph_write_line; bmp->read_bank = ph_write_line; #else bmp->write_bank = ph_write_line_asm; bmp->read_bank = ph_write_line_asm; #endif /* setup surface info structure to store additional information */ bmp->extra = malloc(sizeof(struct BMP_EXTRA_INFO)); BMP_EXTRA(bmp)->context = context; return bmp; } /* destroy_photon_bitmap: * Destroys a video bitmap. */ void destroy_photon_bitmap(BITMAP *bmp) { if (bmp) { free(bmp->extra); free(bmp); } } /* qnx_ph_created_sub_bitmap: */ void qnx_ph_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { bmp->extra = parent; } /* qnx_ph_create_video_bitmap: */ BITMAP *qnx_ph_create_video_bitmap(int width, int height) { PdOffscreenContext_t *context; int flags = Pg_OSC_MEM_PAGE_ALIGN; if ((width == screen->w) && (height == screen->h)) { if (!reused_screen) { reused_screen = TRUE; return screen; } flags |= Pg_OSC_CRTC_SAFE; } context = PdCreateOffscreenContext(0, width, height, flags); if (!context) return NULL; return make_photon_bitmap(context, width, height, BMP_ID_VIDEO); } /* qnx_ph_destroy_video_bitmap: */ void qnx_ph_destroy_video_bitmap(BITMAP *bmp) { if (bmp == screen) { reused_screen = FALSE; return; } if (bmp == ph_frontbuffer) { /* in this case, 'bmp' points to the visible contents * but 'screen' doesn't, so we first invert that */ qnx_ph_show_video_bitmap(screen); } PhDCRelease(BMP_EXTRA(bmp)->context); destroy_photon_bitmap(bmp); } /* swap_video_bitmap: * Worker function for Photon page flipping. */ static int swap_video_bitmap(BITMAP *bmp, int vsync) { if (PgSwapDisplay(BMP_EXTRA(bmp)->context, vsync ? Pg_SWAP_VSYNC : 0) != 0) return -1; PgFlush(); /* ph_frontbuffer must keep track of the forefront bitmap */ ph_frontbuffer = bmp; return 0; } /* qnx_ph_show_video_bitmap: */ int qnx_ph_show_video_bitmap(BITMAP *bmp) { return swap_video_bitmap(bmp, _wait_for_vsync); } /* qnx_ph_request_video_bitmap: */ int qnx_ph_request_video_bitmap(BITMAP *bmp) { return swap_video_bitmap(bmp, FALSE); }