/* * call-seq: * bmp_unwrite_line(bmp, line) -> nil * * Releases the bitmap memory after you are finished with it. You only need to * call this once at the end of a drawing operation, even if you have called * bmp_write_line or bmp_read_line several times before it. */ VALUE a4r_API_bmp_unwrite_line(VALUE self, VALUE bmp) { BITMAP *bitmap; Data_Get_Struct(bmp, BITMAP, bitmap); bmp_unwrite_line(bitmap); return Qnil; }
/* * Engine of anti-aliased stretching. */ static void _aa_stretch_blit (BITMAP *_src, BITMAP *_dst, int _sx, int _sy, int _sw, int _sh, int _dx, int _dy, int _dw, int _dh, int _masked) { int sx, sy, dx, dy, ydx, ysx; int xinc, yinc, dsx, dsy; int xi1, xi2, xdd, yxdd; int yi1, yi2, ydd; int dxbeg, dxend, dybeg, dyend; unsigned long num; void (*add) (BITMAP *_src, int _sx1, int _sx2, int _sy1, int _sy2, unsigned long _num); void (*put) (unsigned long _addr, int _x); if ((_dw <= 0) || (_dh <= 0) || (_sw <= 0) || (_sh <= 0)) return; if (_dst->clip) { dybeg = ((_dy > _dst->ct) ? _dy : _dst->ct); dyend = (((_dy + _dh) < _dst->cb) ? (_dy + _dh) : _dst->cb); if (dybeg >= dyend) return; dxbeg = ((_dx > _dst->cl) ? _dx : _dst->cl); dxend = (((_dx + _dw) < _dst->cr) ? (_dx + _dw) : _dst->cr); if (dxbeg >= dxend) return; } else { dxbeg = _dx; dybeg = _dy; dxend = _dx + _dw; dyend = _dy + _dh; } _sx <<= aa_BITS; _sw <<= aa_BITS; dsx = _sw / _dw; if (dsx < aa_SIZE) { /* Exploding by x. */ _dw--; _sw -= aa_SIZE; dsx = aa_SIZE; } _sy <<= aa_BITS; _sh <<= aa_BITS; dsy = _sh / _dh; if (dsy < aa_SIZE) { /* Exploding by y. */ _dh--; _sh -= aa_SIZE; dsy = aa_SIZE; } num = dsx * dsy; if (num > aa_MAX_NUM) { if (dsx > aa_MAX_SIZE) dsx = aa_MAX_SIZE; if (dsy > aa_MAX_SIZE) dsy = aa_MAX_SIZE; num = dsx * dsy; } /* Walk in x direction up to dxbeg and save Bresenham state there. * Later, it will be used to restart at any line. */ aa_PREPARE (xinc, yxdd, xi1, xi2, _sw, _dw); for (ydx = _dx, ysx = _sx; ydx < dxbeg; ydx++) { aa_ADVANCE (ysx, xinc, yxdd, xi1, xi2); } /* Color manipulation routines. */ if (is_screen_bitmap (_src)) return; else { switch (bitmap_color_depth (_src)) { case 8: add = ((_masked != 0) ? _aa_masked_add_rgb8 : _aa_add_rgb8); break; #ifdef ALLEGRO_COLOR16 case 15: add = ((_masked != 0) ? _aa_masked_add_rgb15 : _aa_add_rgb15); break; case 16: add = ((_masked != 0) ? _aa_masked_add_rgb16 : _aa_add_rgb16); break; #endif #ifdef ALLEGRO_COLOR24 case 24: add = ((_masked != 0) ? _aa_masked_add_rgb24 : _aa_add_rgb24); _aa_prepare_for_24bpp (); break; #endif #ifdef ALLEGRO_COLOR32 case 32: add = ((_masked != 0) ? _aa_masked_add_rgb32 : _aa_add_rgb32); break; #endif default: return; } } if (is_planar_bitmap (_dst)) return; else { switch (bitmap_color_depth (_dst)) { case 8: put = ((_masked != 0) ? _aa_masked_put_rgb8 : _aa_put_rgb8); break; #ifdef ALLEGRO_COLOR16 case 15: put = ((_masked != 0) ? _aa_masked_put_rgb15 : _aa_put_rgb15); break; case 16: put = ((_masked != 0) ? _aa_masked_put_rgb16 : _aa_put_rgb16); break; #endif #ifdef ALLEGRO_COLOR24 case 24: put = ((_masked != 0) ? _aa_masked_put_rgb24 : _aa_put_rgb24); _aa_prepare_for_24bpp (); break; #endif #ifdef ALLEGRO_COLOR32 case 32: put = ((_masked != 0) ? _aa_masked_put_rgb32 : _aa_put_rgb32); break; #endif default: return; } } /* Walk in y until we reach first non-clipped line. */ aa_PREPARE (yinc, ydd, yi1, yi2, _sh, _dh); for (dy = _dy, sy = _sy; dy < dybeg; dy++) { aa_ADVANCE (sy, yinc, ydd, yi1, yi2); } bmp_select (_dst); /* Stretch all non-clipped lines. */ for (; dy < dyend; dy++) { unsigned long daddr = bmp_write_line (_dst, dy); for (dx = ydx, sx = ysx, xdd = yxdd; dx < dxend; dx++) { (*add) (_src, sx, sx + dsx, sy, sy + dsy, num); (*put) (daddr, dx); aa_ADVANCE (sx, xinc, xdd, xi1, xi2); } aa_ADVANCE (sy, yinc, ydd, yi1, yi2); } bmp_unwrite_line (_dst); }
/* _set_gfx_mode: * Called by set_gfx_mode(). Separated to make a clear difference between * the virtual GFX_SAFE driver and the rest. The allow_config parameter, * if true, allows the configuration to override the graphics card/driver * when using GFX_AUTODETECT. */ static int _set_gfx_mode(int card, int w, int h, int v_w, int v_h, int allow_config) { _DRIVER_INFO *driver_list; GFX_DRIVER *drv; char tmp1[64], tmp2[64]; AL_CONST char *dv; int flags = 0; int c; ASSERT(system_driver); ASSERT(card != GFX_SAFE); /* remember the current console state */ if (gfx_virgin) { TRACE(PREFIX_I "First call, remembering console state.\n"); LOCK_FUNCTION(_stub_bank_switch); LOCK_FUNCTION(blit); if (system_driver->save_console_state) system_driver->save_console_state(); _add_exit_func(shutdown_gfx, "shutdown_gfx"); gfx_virgin = FALSE; } timer_simulate_retrace(FALSE); _screen_split_position = 0; /* close down any existing graphics driver */ if (gfx_driver) { TRACE(PREFIX_I "Closing graphics driver (%p) ", gfx_driver); TRACE("%s.\n", gfx_driver->ascii_name); if (_al_linker_mouse) _al_linker_mouse->show_mouse(NULL); while (vram_bitmap_list) destroy_bitmap(vram_bitmap_list->bmp); bmp_read_line(screen, 0); bmp_write_line(screen, 0); bmp_unwrite_line(screen); if (gfx_driver->scroll) gfx_driver->scroll(0, 0); if (gfx_driver->exit) gfx_driver->exit(screen); destroy_bitmap(screen); gfx_driver = NULL; screen = NULL; gfx_capabilities = 0; } /* We probably don't want to do this because it makes * Allegro "forget" the color layout of previously set * graphics modes. But it should be retained if bitmaps * created in those modes are to be used in the new mode. */ #if 0 /* restore default truecolor pixel format */ _rgb_r_shift_15 = 0; _rgb_g_shift_15 = 5; _rgb_b_shift_15 = 10; _rgb_r_shift_16 = 0; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 11; _rgb_r_shift_24 = 0; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 16; _rgb_r_shift_32 = 0; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 16; _rgb_a_shift_32 = 24; #endif gfx_capabilities = 0; _set_current_refresh_rate(0); /* return to text mode? */ if (card == GFX_TEXT) { TRACE(PREFIX_I "Closing, restoring original console state.\n"); if (system_driver->restore_console_state) system_driver->restore_console_state(); if (_gfx_bank) { _AL_FREE(_gfx_bank); _gfx_bank = NULL; } TRACE(PREFIX_I "Graphic mode closed.\n"); return 0; } /* now to the interesting part: let's try to find a graphics driver */ usetc(allegro_error, 0); /* ask the system driver for a list of graphics hardware drivers */ if (system_driver->gfx_drivers) driver_list = system_driver->gfx_drivers(); else driver_list = _gfx_driver_list; /* filter specific fullscreen/windowed driver requests */ if (card == GFX_AUTODETECT_FULLSCREEN) { flags |= GFX_DRIVER_FULLSCREEN_FLAG; card = GFX_AUTODETECT; } else if (card == GFX_AUTODETECT_WINDOWED) { flags |= GFX_DRIVER_WINDOWED_FLAG; card = GFX_AUTODETECT; } if (card == GFX_AUTODETECT) { /* autodetect the driver */ int found = FALSE; tmp1[0] = '\0'; /* first try the config variables */ if (allow_config) { /* try the gfx_card variable if GFX_AUTODETECT or GFX_AUTODETECT_FULLSCREEN was selected */ if (!(flags & GFX_DRIVER_WINDOWED_FLAG)) found = get_config_gfx_driver(uconvert_ascii("gfx_card", tmp1), w, h, v_w, v_h, flags, driver_list); /* try the gfx_cardw variable if GFX_AUTODETECT or GFX_AUTODETECT_WINDOWED was selected */ if (!(flags & GFX_DRIVER_FULLSCREEN_FLAG) && !found) found = get_config_gfx_driver(uconvert_ascii("gfx_cardw", tmp1), w, h, v_w, v_h, flags, driver_list); } /* go through the list of autodetected drivers if none was previously found */ if (!found) { TRACE(PREFIX_I "Autodetecting graphic driver.\n"); for (c=0; driver_list[c].driver; c++) { if (driver_list[c].autodetect) { drv = driver_list[c].driver; if (gfx_driver_is_valid(drv, flags)) { screen = init_gfx_driver(drv, w, h, v_w, v_h); if (screen) break; } } } } else { TRACE(PREFIX_I "GFX_AUTODETECT overridden through configuration:" " %s.\n", tmp1); } } else { /* search the list for the requested driver */ drv = get_gfx_driver_from_id(card, driver_list); if (drv) screen = init_gfx_driver(drv, w, h, v_w, v_h); } /* gracefully handle failure */ if (!screen) { gfx_driver = NULL; /* set by init_gfx_driver() */ if (!ugetc(allegro_error)) ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unable to find a suitable graphics driver")); TRACE(PREFIX_E "Failed setting graphic driver %d.\n", card); return -1; } /* set the basic capabilities of the driver */ if ((VIRTUAL_W > SCREEN_W) || (VIRTUAL_H > SCREEN_H)) { if (gfx_driver->scroll) gfx_capabilities |= GFX_CAN_SCROLL; if ((gfx_driver->request_scroll) || (gfx_driver->request_video_bitmap)) gfx_capabilities |= GFX_CAN_TRIPLE_BUFFER; } /* check whether we are instructed to disable vsync */ dv = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("disable_vsync", tmp2), NULL); if ((dv) && ((c = ugetc(dv)) != 0) && ((c == 'y') || (c == 'Y') || (c == '1'))) _wait_for_vsync = FALSE; else _wait_for_vsync = TRUE; TRACE(PREFIX_I "The driver %s wait for vsync.\n", (_wait_for_vsync) ? "will" : "won't"); /* Give the gfx driver an opportunity to set the drawing mode */ if ((gfx_driver->drawing_mode) && (!_dispsw_status)) gfx_driver->drawing_mode(); clear_bitmap(screen); /* set up the default colors */ for (c=0; c<256; c++) _palette_color8[c] = c; set_palette(default_palette); if (_al_linker_mouse) _al_linker_mouse->set_mouse_etc(); LOCK_DATA(gfx_driver, sizeof(GFX_DRIVER)); _register_switch_bitmap(screen, NULL); TRACE(PREFIX_I "set_gfx_card success for %dx%dx%d.\n", screen->w, screen->h, bitmap_color_depth(screen)); return 0; }
void SuperEagle_ex(uint8 *src, uint32 src_pitch, uint8 *unused, ALLEGRO_BITMAP *dest, uint32 width, uint32 height) { int j, v; unsigned int x, y; int sbpp = BYTES_PER_PIXEL(bitmap_color_depth(dest)); unsigned long color[12]; unsigned char **src_line = new unsigned char*[4]; unsigned char **dst_line = new unsigned char*[2]; /* Point to the first 3 lines. */ src_line[0] = src; src_line[1] = src; src_line[2] = src + src_pitch; src_line[3] = src + src_pitch * 2; /* Can we write the results directly? */ if (is_video_bitmap(dest) || is_planar_bitmap(dest)) { //dst_line[0] = malloc(sizeof(char) * sbpp * width); //dst_line[1] = malloc(sizeof(char) * sbpp * width); dst_line[0] = new unsigned char[sbpp*width]; dst_line[1] = new unsigned char[sbpp*width]; v = 1; } else { dst_line[0] = dest->line[0]; dst_line[1] = dest->line[1]; v = 0; } /* Set destination */ bmp_select(dest); x = 0, y = 0; if (PixelsPerMask == 2) { unsigned short *sbp; sbp = (unsigned short*)src_line[0]; color[0] = *sbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0]; color[4] = *(sbp + 1); color[5] = *(sbp + 2); sbp = (unsigned short*)src_line[2]; color[6] = *sbp; color[7] = color[6]; color[8] = *(sbp + 1); color[9] = *(sbp + 2); sbp = (unsigned short*)src_line[3]; color[10] = *sbp; color[11] = *(sbp + 1); } else { unsigned long *lbp; lbp = (unsigned long*)src_line[0]; color[0] = *lbp; color[1] = color[0]; color[2] = color[0]; color[3] = color[0]; color[4] = *(lbp + 1); color[5] = *(lbp + 2); lbp = (unsigned long*)src_line[2]; color[6] = *lbp; color[7] = color[6]; color[8] = *(lbp + 1); color[9] = *(lbp + 2); lbp = (unsigned long*)src_line[3]; color[10] = *lbp; color[11] = *(lbp + 1); } for (y = 0; y < height; y++) { /* Todo: x = width - 2, x = width - 1 */ for (x = 0; x < width; x++) { unsigned long product1a, product1b, product2a, product2b; //--------------------------------------- B1 B2 0 1 // 4 5 6 S2 -> 2 3 4 5 // 1 2 3 S1 6 7 8 9 // A1 A2 10 11 if (color[7] == color[4] && color[3] != color[8]) { product1b = product2a = color[7]; if ((color[6] == color[7]) || (color[4] == color[1])) product1a = INTERPOLATE(color[7], INTERPOLATE(color[7], color[3])); else product1a = INTERPOLATE(color[3], color[4]); if ((color[4] == color[5]) || (color[7] == color[10])) product2b = INTERPOLATE(color[7], INTERPOLATE(color[7], color[8])); else product2b = INTERPOLATE(color[7], color[8]); } else if (color[3] == color[8] && color[7] != color[4]) { product2b = product1a = color[3]; if ((color[0] == color[3]) || (color[5] == color[9])) product1b = INTERPOLATE(color[3], INTERPOLATE(color[3], color[4])); else product1b = INTERPOLATE(color[3], color[1]); if ((color[8] == color[11]) || (color[2] == color[3])) product2a = INTERPOLATE(color[3], INTERPOLATE(color[3], color[2])); else product2a = INTERPOLATE(color[7], color[8]); } else if (color[3] == color[8] && color[7] == color[4]) { register int r = 0; r += GET_RESULT(color[4], color[3], color[6], color[10]); r += GET_RESULT(color[4], color[3], color[2], color[0]); r += GET_RESULT(color[4], color[3], color[11], color[9]); r += GET_RESULT(color[4], color[3], color[1], color[5]); if (r > 0) { product1b = product2a = color[7]; product1a = product2b = INTERPOLATE(color[3], color[4]); } else if (r < 0) { product2b = product1a = color[3]; product1b = product2a = INTERPOLATE(color[3], color[4]); } else { product2b = product1a = color[3]; product1b = product2a = color[7]; } } else { product2b = product1a = INTERPOLATE(color[7], color[4]); product2b = Q_INTERPOLATE(color[8], color[8], color[8], product2b); product1a = Q_INTERPOLATE(color[3], color[3], color[3], product1a); product2a = product1b = INTERPOLATE(color[3], color[8]); product2a = Q_INTERPOLATE(color[7], color[7], color[7], product2a); product1b = Q_INTERPOLATE(color[4], color[4], color[4], product1b); } if (PixelsPerMask == 2) { *((unsigned long *) (&dst_line[0][x * 4])) = product1a | (product1b << 16); *((unsigned long *) (&dst_line[1][x * 4])) = product2a | (product2b << 16); } else { *((unsigned long *) (&dst_line[0][x * 8])) = product1a; *((unsigned long *) (&dst_line[0][x * 8 + 4])) = product1b; *((unsigned long *) (&dst_line[1][x * 8])) = product2a; *((unsigned long *) (&dst_line[1][x * 8 + 4])) = product2b; } /* Move color matrix forward */ color[0] = color[1]; color[2] = color[3]; color[3] = color[4]; color[4] = color[5]; color[6] = color[7]; color[7] = color[8]; color[8] = color[9]; color[10] = color[11]; if (x < width - 2) { x += 2; if (PixelsPerMask == 2) { color[1] = *(((unsigned short*)src_line[0]) + x); if (x < width) { color[5] = *(((unsigned short*)src_line[1]) + x + 1); color[9] = *(((unsigned short*)src_line[2]) + x + 1); } color[11] = *(((unsigned short*)src_line[3]) + x); } else { color[1] = *(((unsigned long*)src_line[0]) + x); if (x < width) { color[5] = *(((unsigned long*)src_line[1]) + x + 1); color[9] = *(((unsigned long*)src_line[2]) + x + 1); } color[11] = *(((unsigned long*)src_line[3]) + x); } x -= 2; } } /* We're done with one line, so we shift the source lines up */ src_line[0] = src_line[1]; src_line[1] = src_line[2]; src_line[2] = src_line[3]; /* Read next line */ if (y + 3 >= height) src_line[3] = src_line[2]; else src_line[3] = src_line[2] + src_pitch; /* Then shift the color matrix up */ if (PixelsPerMask == 2) { unsigned short *sbp; sbp = (unsigned short*)src_line[0]; color[0] = *sbp; color[1] = *(sbp + 1); sbp = (unsigned short*)src_line[1]; color[2] = *sbp; color[3] = color[2]; color[4] = *(sbp + 1); color[5] = *(sbp + 2); sbp = (unsigned short*)src_line[2]; color[6] = *sbp; color[7] = color[6]; color[8] = *(sbp + 1); color[9] = *(sbp + 2); sbp = (unsigned short*)src_line[3]; color[10] = *sbp; color[11] = *(sbp + 1); } else { unsigned long *lbp; lbp = (unsigned long*)src_line[0]; color[0] = *lbp; color[1] = *(lbp + 1); lbp = (unsigned long*)src_line[1]; color[2] = *lbp; color[3] = color[2]; color[4] = *(lbp + 1); color[5] = *(lbp + 2); lbp = (unsigned long*)src_line[2]; color[6] = *lbp; color[7] = color[6]; color[8] = *(lbp + 1); color[9] = *(lbp + 2); lbp = (unsigned long*)src_line[3]; color[10] = *lbp; color[11] = *(lbp + 1); } /* Write the 2 lines, if not already done so */ if (v) { unsigned long dst_addr; dst_addr = bmp_write_line(dest, y * 2); for (j = 0; j < dest->w * sbpp; j += sizeof(long)) bmp_write32(dst_addr + j, *((unsigned long *) (dst_line[0] + j))); dst_addr = bmp_write_line(dest, y * 2 + 1); for (j = 0; j < dest->w * sbpp; j += sizeof(long)) bmp_write32(dst_addr + j, *((unsigned long *) (dst_line[1] + j))); } else { if (y < height - 1) { dst_line[0] = dest->line[y * 2 + 2]; dst_line[1] = dest->line[y * 2 + 3]; } } } bmp_unwrite_line(dest); if (v) { delete dst_line[0]; delete dst_line[1]; } delete[] src_line; delete[] dst_line; }