示例#1
0
void init_compiler(
	struct radeon_compiler *c,
	enum rc_program_type program_type,
	unsigned is_r500,
	unsigned is_r400)
{
	struct rc_regalloc_state *rs = malloc(sizeof(struct rc_regalloc_state));
	rc_init_regalloc_state(rs);
	rc_init(c, rs);

	c->is_r500 = is_r500;
	c->max_temp_regs = is_r500 ? 128 : (is_r400 ? 64 : 32);
	c->max_constants = is_r500 ? 256 : 32;
	c->max_alu_insts = (is_r500 || is_r400) ? 512 : 64;
	c->max_tex_insts = (is_r500 || is_r400) ? 512 : 32;
	if (program_type == RC_FRAGMENT_PROGRAM) {
		c->has_half_swizzles = 1;
		c->has_presub = 1;
		c->has_omod = 1;
		c->SwizzleCaps =
			is_r500 ? &r500_swizzle_caps : &r300_swizzle_caps;
	} else {
		c->SwizzleCaps = &r300_vertprog_swizzle_caps;
	}
}
示例#2
0
int
gs_push_device_filter(gs_memory_t *mem, gs_state *pgs, gs_device_filter_t *df)
{
    gs_device_filter_stack_t *dfs;
    gx_device *new_dev = NULL;
    int code;

    dfs = gs_alloc_struct(mem, gs_device_filter_stack_t,
			  &st_gs_device_filter_stack, "gs_push_device_filter");
    if (dfs == NULL)
	return_error(gs_error_VMerror);
    rc_increment(pgs->device);
    dfs->next_device = pgs->device;
    code = df->push(df, mem, pgs, &new_dev, pgs->device);
    if (code < 0) {
	gs_free_object(mem, dfs, "gs_push_device_filter");
	return code;
    }
    dfs->next = pgs->dfilter_stack;
    pgs->dfilter_stack = dfs;
    dfs->df = df;
    rc_init(dfs, mem, 1);
    gs_setdevice_no_init(pgs, new_dev);
    rc_decrement_only(new_dev, "gs_push_device_filter");
    return code;
}
示例#3
0
static inline void main_init( void ) {
    hw_init();
    sys_time_init();
    led_init();

    comm_init(COMM_TELEMETRY);

    rc_init();

    int_enable();
}
int main(int argc, char **argv)
{
  rc_init(
    on_pre_conn,
    on_connection,
    on_completion,
    on_disconnect);

  printf("waiting for connections. interrupt (^C) to exit.\n");

  rc_server_loop(DEFAULT_PORT);

  return 0;
}
示例#5
0
void r300_translate_vertex_shader(struct r300_context* r300,
                                  struct r300_vertex_shader* vs)
{
    struct r300_vertex_program_compiler compiler;
    struct tgsi_to_rc ttr;

    /* Initialize. */
    r300_shader_read_vs_outputs(&vs->info, &vs->outputs);

    /* Setup the compiler */
    rc_init(&compiler.Base);

    compiler.Base.Debug = DBG_ON(r300, DBG_VP);
    compiler.code = &vs->code;
    compiler.UserData = vs;

    if (compiler.Base.Debug) {
        debug_printf("r300: Initial vertex program\n");
        tgsi_dump(vs->state.tokens, 0);
    }

    /* Translate TGSI to our internal representation */
    ttr.compiler = &compiler.Base;
    ttr.info = &vs->info;
    ttr.use_half_swizzles = FALSE;

    r300_tgsi_to_rc(&ttr, vs->state.tokens);

    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1));
    compiler.SetHwInputOutput = &set_vertex_inputs_outputs;

    /* Insert the WPOS output. */
    r300_insert_wpos(&compiler, &vs->outputs);

    r300_shader_vap_output_fmt(vs);
    r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);

    /* Invoke the compiler */
    r3xx_compile_vertex_program(&compiler);
    if (compiler.Base.Error) {
        /* XXX We should fallback using Draw. */
        fprintf(stderr, "r300 VP: Compiler error\n");
        abort();
    }

    /* And, finally... */
    rc_destroy(&compiler.Base);
    vs->translated = TRUE;
}
示例#6
0
int BBBlueADC::init()
{
	rc_init();

	int ret = DriverFramework::VirtDevObj::init();

	if (ret != PX4_OK) {
		PX4_ERR("init failed");
		return ret;
	}

	_measure(); // start the initial conversion so that the test command right
	// after the start command can return values
	return PX4_OK;
}
示例#7
0
void r300_translate_fragment_shader(struct r300_context* r300,
                                    struct r300_fragment_shader* fs)
{
    struct r300_fragment_program_compiler compiler;
    struct tgsi_to_rc ttr;

    memset(&compiler, 0, sizeof(compiler));
    rc_init(&compiler.Base);
    compiler.Base.Debug = DBG_ON(r300, DBG_FP);

    compiler.code = &fs->code;
    compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500;
    compiler.AllocateHwInputs = &allocate_hardware_inputs;
    compiler.UserData = fs;

    /* TODO: Program compilation depends on texture compare modes,
     * which are sampler state. Therefore, programs need to be recompiled
     * depending on this state as in the classic Mesa driver.
     *
     * This is not yet handled correctly.
     */

    find_output_registers(&compiler, fs);

    if (compiler.Base.Debug) {
        debug_printf("r300: Initial fragment program\n");
        tgsi_dump(fs->state.tokens, 0);
    }

    /* Translate TGSI to our internal representation */
    ttr.compiler = &compiler.Base;
    ttr.info = &fs->info;

    r300_tgsi_to_rc(&ttr, fs->state.tokens);

    /* Invoke the compiler */
    r3xx_compile_fragment_program(&compiler);
    if (compiler.Base.Error) {
        /* XXX failover maybe? */
        DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n",
            compiler.Base.ErrorMsg);
    }

    /* And, finally... */
    rc_destroy(&compiler.Base);
    fs->translated = TRUE;
}
示例#8
0
static inline void autopilot_main_init( void ) {
  hw_init();
  sys_time_init();
  led_init();

  supervision_init();
  actuators_init(ACTUATOR_BANK_MOTORS);

#if BOMB_ENABLED
  bomb_init_servo(RADIO_FMS, 0, 0);
#endif

  rc_init();

#if HARDWARE_ENABLED_GPS
  gps_init();
#else
  comm_init(COMM_0);
  comm_add_tx_callback(COMM_0, comm_autopilot_message_send);
  comm_add_rx_callback(COMM_0, comm_autopilot_message_received);
#endif

  comm_init(COMM_TELEMETRY);
  comm_add_tx_callback(COMM_TELEMETRY, comm_autopilot_message_send);
  comm_add_rx_callback(COMM_TELEMETRY, comm_autopilot_message_received);

  analog_init();
  analog_enable_channel(ANALOG_CHANNEL_BATTERY);
  analog_enable_channel(ANALOG_CHANNEL_PRESSURE);

  altimeter_init();

  imu_init();

  autopilot_init();

  ahrs_init();
  ins_init();

  fms_init();

  int_enable();
}
示例#9
0
int main(void)
{
	int8_t i;
	
	rc_init();
	rfm70_init(RFM70_MODE_PTX, rfm70_addr);
	RED_LED_OUT();
	RED_LED_OFF();
	sei();
	
	while(1) {
		rc_get_code(&code);
		//RED_LED_TOGGLE();
		
		tx_buf[0] = code.addr;
		tx_buf[1] = code.data;
#if 0		
		for(i = 7; i >= 0; i--)
		{
			if(code.data & (1 << i)) {
				RED_LED_ON();
				_delay_ms(50);
				RED_LED_OFF();
				_delay_ms(50);
			}
			RED_LED_ON();
			_delay_ms(50);
			RED_LED_OFF();
			_delay_ms(50);
				
			_delay_ms(500);
		}
#endif
	
		if(0 == rfm70_transmit_packet(tx_buf,sizeof(tx_buf))) {
			RED_LED_TOGGLE();
		}	

	
		_delay_ms(70);
	
	}
}
示例#10
0
int main()
{
  input_t rc;
  rc_init(&rc);

  uint32_t ev;

	while(1)
	{
		rc.read(&ev);
		if(0xff != ev)
		{
			printf("d: %d x: %x\n", ev, ev);
		}
	}

  rc_deinit();
  return 0;
}
示例#11
0
文件: init.c 项目: heelhook/cronosII
void cronos_init (void) {
  config = g_new0 (Conf, 1);

  /* Defaults */
  config->account_head		= NULL;
  config->mailbox_head		= NULL;
#if USE_PLUGINS
  config->module_head		= NULL;
#endif
  config->empty_garbage		= FALSE;
  config->check_timeout		= 30;
  config->check_at_start	= FALSE;
  config->use_outbox		= TRUE;
  config->prepend_char_on_re	= g_strdup ("> ");
  config->message_bigger	= 0;
  config->timeout		= 15;
  config->mark_as_read		= 1;
  config->default_mime_part	= INIT_DEFAULT_MIME_PART_PLAIN;
#ifdef BUILD_ADDRESS_BOOK
  config->addrbook_init		= INIT_ADDRESS_BOOK_INIT_START;
#endif
  config->use_persistent_smtp_connection = 0;
  config->persistent_smtp_address = NULL;
  config->persistent_smtp_port = 25;

  config->color_reply_original_message.pixel = 0;
  config->color_reply_original_message.red = 0;
  config->color_reply_original_message.green = 0;
  config->color_reply_original_message.blue = 0xffff;
  config->color_misc_body.red = 0;
  config->color_misc_body.green = 0;
  config->color_misc_body.blue = 0;
  config->color_misc_body.pixel = 0;
  
  /* File */
  file_init (config);

  rc_init ();
#if USE_PLUGINS
  c2_dynamic_module_autoload ();
#endif
}
示例#12
0
文件: rc.c 项目: andybug/spreden
int rc_read_options(struct state *s, int argc, char **argv)
{
	struct rc *rc = &s->rc;
	enum command cmd = COMMAND_HELP;
	int err;
	int cmd_index;

	/* save off how the program was called for error displays */
	progname = argv[0];

	/* setup rc with default values */
	rc_init(rc);

	/*
	 * parse all long options
	 * cmd_index will contain the index into argc
	 * that will hold the command
	 */
	if ((cmd_index = parse_options(rc, argc, argv)) < 0)
		return -1;

	/*
	 * if a command was provided, try to parse it
	 * otherwise, fall through to help
	 */
	if ((argc-cmd_index) > 0)
		cmd = get_command(argv[cmd_index]);

	switch (cmd) {
	case COMMAND_ANALYZE:
		rc->action = ACTION_ANALYZE;
		break;
	case COMMAND_HELP:
		rc->action = ACTION_USAGE;
		break;
	case COMMAND_PREDICT:
		rc->action = ACTION_PREDICT;
		break;
	case COMMAND_RANK:
		rc->action = ACTION_RANK;
		break;
	case COMMAND_VERSION:
		rc->action = ACTION_VERSION;
		break;
	case COMMAND_ERROR:
		return -2;
	}

	/* handle <sport> <target week(s)> <algorithms> */
	if (rc->action == ACTION_ANALYZE ||
	    rc->action == ACTION_PREDICT ||
	    rc->action == ACTION_RANK) {
		/*
		 * calculate new argc from cmd_index to the
		 * end of the argument vector
		 * shift the argument vector so that argv[0]
		 * is the first argument after the command from
		 * the command line
		 */
		int new_argc = argc - cmd_index - 1;
		char **new_argv = argv + (cmd_index + 1);

		/*
		 * parse the special sequence of arguments
		 * for these commands
		 */
		err = parse_rc_args(rc, new_argc, new_argv);
		if (err)
			return -3;
	}

	return 0;
}
示例#13
0
static struct r300_vertex_program *build_program(GLcontext *ctx,
						 struct r300_vertex_program_key *wanted_key,
						 const struct gl_vertex_program *mesa_vp)
{
	struct r300_vertex_program *vp;
	struct r300_vertex_program_compiler compiler;

	vp = _mesa_calloc(sizeof(*vp));
	vp->Base = (struct gl_vertex_program *) _mesa_clone_program(ctx, &mesa_vp->Base);
	_mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));

	rc_init(&compiler.Base);
	compiler.Base.Debug = (RADEON_DEBUG & RADEON_VERTS) ? GL_TRUE : GL_FALSE;

	compiler.code = &vp->code;
	compiler.RequiredOutputs = compute_required_outputs(vp->Base, vp->key.FpReads);
	compiler.SetHwInputOutput = &t_inputs_outputs;

	if (compiler.Base.Debug) {
		fprintf(stderr, "Initial vertex program:\n");
		_mesa_print_program(&vp->Base->Base);
		fflush(stderr);
	}

	if (mesa_vp->IsPositionInvariant) {
		_mesa_insert_mvp_code(ctx, vp->Base);
	}

	radeon_mesa_to_rc_program(&compiler.Base, &vp->Base->Base);

	if (mesa_vp->IsNVProgram)
		initialize_NV_registers(&compiler.Base);

	rc_move_output(&compiler.Base, VERT_RESULT_PSIZ, VERT_RESULT_PSIZ, WRITEMASK_X);

	if (vp->key.WPosAttr != FRAG_ATTRIB_MAX) {
		rc_copy_output(&compiler.Base,
			VERT_RESULT_HPOS,
			vp->key.WPosAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0);
	}

	if (vp->key.FogAttr != FRAG_ATTRIB_MAX) {
		rc_move_output(&compiler.Base,
			VERT_RESULT_FOGC,
			vp->key.FogAttr - FRAG_ATTRIB_TEX0 + VERT_RESULT_TEX0, WRITEMASK_X);
	}

	r3xx_compile_vertex_program(&compiler);

	if (vp->code.constants.Count > ctx->Const.VertexProgram.MaxParameters) {
		rc_error(&compiler.Base, "Program exceeds constant buffer size limit\n");
	}

	vp->error = compiler.Base.Error;

	vp->Base->Base.InputsRead = vp->code.InputsRead;
	vp->Base->Base.OutputsWritten = vp->code.OutputsWritten;

	rc_destroy(&compiler.Base);

	return vp;
}
示例#14
0
void r300_translate_vertex_shader(struct r300_context *r300,
                                  struct r300_vertex_shader *vs)
{
    struct r300_vertex_program_compiler compiler;
    struct tgsi_to_rc ttr;
    unsigned i;

    /* Setup the compiler */
    memset(&compiler, 0, sizeof(compiler));
    rc_init(&compiler.Base, NULL);

    DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
    DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0;
    compiler.code = &vs->code;
    compiler.UserData = vs;
    compiler.Base.is_r500 = r300->screen->caps.is_r500;
    compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
    compiler.Base.has_half_swizzles = FALSE;
    compiler.Base.has_presub = FALSE;
    compiler.Base.has_omod = FALSE;
    compiler.Base.max_temp_regs = 32;
    compiler.Base.max_constants = 256;
    compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256;

    if (compiler.Base.Debug & RC_DBG_LOG) {
        DBG(r300, DBG_VP, "r300: Initial vertex program\n");
        tgsi_dump(vs->state.tokens, 0);
    }

    /* Translate TGSI to our internal representation */
    ttr.compiler = &compiler.Base;
    ttr.info = &vs->info;
    ttr.use_half_swizzles = FALSE;

    r300_tgsi_to_rc(&ttr, vs->state.tokens);

    if (ttr.error) {
        fprintf(stderr, "r300 VP: Cannot translate a shader. "
                "Using a dummy shader instead.\n");
        r300_dummy_vertex_shader(r300, vs);
        return;
    }

    if (compiler.Base.Program.Constants.Count > 200) {
        compiler.Base.remove_unused_constants = TRUE;
    }

    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1));
    compiler.SetHwInputOutput = &set_vertex_inputs_outputs;

    /* Insert the WPOS output. */
    rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);

    /* Invoke the compiler */
    r3xx_compile_vertex_program(&compiler);
    if (compiler.Base.Error) {
        fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
                " instead.\n", compiler.Base.ErrorMsg);

        if (vs->dummy) {
            fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
                    "Giving up...\n");
            abort();
        }

        rc_destroy(&compiler.Base);
        r300_dummy_vertex_shader(r300, vs);
        return;
    }

    /* Initialize numbers of constants for each type. */
    vs->externals_count = 0;
    for (i = 0;
            i < vs->code.constants.Count &&
            vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
        vs->externals_count = i+1;
    }
    for (; i < vs->code.constants.Count; i++) {
        assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE);
    }
    vs->immediates_count = vs->code.constants.Count - vs->externals_count;

    /* And, finally... */
    rc_destroy(&compiler.Base);
}
示例#15
0
文件: r300_fs.c 项目: nikai3d/mesa
static void r300_translate_fragment_shader(
    struct r300_context* r300,
    struct r300_fragment_shader_code* shader,
    const struct tgsi_token *tokens)
{
    struct r300_fragment_program_compiler compiler;
    struct tgsi_to_rc ttr;
    int wpos, face;
    unsigned i;

    tgsi_scan_shader(tokens, &shader->info);
    r300_shader_read_fs_inputs(&shader->info, &shader->inputs);

    wpos = shader->inputs.wpos;
    face = shader->inputs.face;

    /* Setup the compiler. */
    memset(&compiler, 0, sizeof(compiler));
    rc_init(&compiler.Base);
    DBG_ON(r300, DBG_FP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
    DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0;

    compiler.code = &shader->code;
    compiler.state = shader->compare_state;
    compiler.Base.is_r500 = r300->screen->caps.is_r500;
    compiler.Base.is_r400 = r300->screen->caps.is_r400;
    compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
    compiler.Base.has_half_swizzles = TRUE;
    compiler.Base.has_presub = TRUE;
    compiler.Base.max_temp_regs =
        compiler.Base.is_r500 ? 128 : (compiler.Base.is_r400 ? 64 : 32);
    compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32;
    compiler.Base.max_alu_insts =
        (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 64;
    compiler.Base.max_tex_insts =
        (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 32;
    compiler.AllocateHwInputs = &allocate_hardware_inputs;
    compiler.UserData = &shader->inputs;

    find_output_registers(&compiler, shader);

    shader->write_all = FALSE;
    for (i = 0; i < shader->info.num_properties; i++) {
        if (shader->info.properties[i].name == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
            shader->write_all = TRUE;
        }
    }

    if (compiler.Base.Debug & RC_DBG_LOG) {
        DBG(r300, DBG_FP, "r300: Initial fragment program\n");
        tgsi_dump(tokens, 0);
    }

    /* Translate TGSI to our internal representation */
    ttr.compiler = &compiler.Base;
    ttr.info = &shader->info;
    ttr.use_half_swizzles = TRUE;

    r300_tgsi_to_rc(&ttr, tokens);

    if (ttr.error) {
        fprintf(stderr, "r300 FP: Cannot translate a shader. "
                "Using a dummy shader instead.\n");
        r300_dummy_fragment_shader(r300, shader);
        return;
    }

    if (!r300->screen->caps.is_r500 ||
        compiler.Base.Program.Constants.Count > 200) {
        compiler.Base.remove_unused_constants = TRUE;
    }

    /**
     * Transform the program to support WPOS.
     *
     * Introduce a small fragment at the start of the program that will be
     * the only code that directly reads the WPOS input.
     * All other code pieces that reference that input will be rewritten
     * to read from a newly allocated temporary. */
    if (wpos != ATTR_UNUSED) {
        /* Moving the input to some other reg is not really necessary. */
        rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE);
    }

    if (face != ATTR_UNUSED) {
        rc_transform_fragment_face(&compiler.Base, face);
    }

    /* Invoke the compiler */
    r3xx_compile_fragment_program(&compiler);

    if (compiler.Base.Error) {
        fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader"
                " instead.\n", compiler.Base.ErrorMsg);

        if (shader->dummy) {
            fprintf(stderr, "r300 FP: Cannot compile the dummy shader! "
                    "Giving up...\n");
            abort();
        }

        rc_destroy(&compiler.Base);
        r300_dummy_fragment_shader(r300, shader);
        return;
    }

    /* Shaders with zero instructions are invalid,
     * use the dummy shader instead. */
    if (shader->code.code.r500.inst_end == -1) {
        rc_destroy(&compiler.Base);
        r300_dummy_fragment_shader(r300, shader);
        return;
    }

    /* Initialize numbers of constants for each type. */
    shader->externals_count = 0;
    for (i = 0;
         i < shader->code.constants.Count &&
         shader->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
        shader->externals_count = i+1;
    }
    shader->immediates_count = 0;
    shader->rc_state_count = 0;

    for (i = shader->externals_count; i < shader->code.constants.Count; i++) {
        switch (shader->code.constants.Constants[i].Type) {
            case RC_CONSTANT_IMMEDIATE:
                ++shader->immediates_count;
                break;
            case RC_CONSTANT_STATE:
                ++shader->rc_state_count;
                break;
            default:
                assert(0);
        }
    }

    /* Setup shader depth output. */
    if (shader->code.writes_depth) {
        shader->fg_depth_src = R300_FG_DEPTH_SRC_SHADER;
        shader->us_out_w = R300_W_FMT_W24 | R300_W_SRC_US;
    } else {
        shader->fg_depth_src = R300_FG_DEPTH_SRC_SCAN;
        shader->us_out_w = R300_W_FMT_W0 | R300_W_SRC_US;
    }

    /* And, finally... */
    rc_destroy(&compiler.Base);

    /* Build the command buffer. */
    r300_emit_fs_code_to_buffer(r300, shader);
}
示例#16
0
文件: gsdevmem.c 项目: aberg001/plan9
/* We separate device allocation and initialization at customer request. */
int
gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat,
                              uint width, uint height, const byte * colors, int colors_size,
                              bool word_oriented, bool page_device, gs_memory_t * mem)
{
    const gx_device_memory *proto_dev;
    int palette_count = colors_size;
    int num_components = 1;
    int pcount;
    int bits_per_pixel;
    float x_pixels_per_unit, y_pixels_per_unit;
    byte palette[256 * 3];
    bool has_color;

    switch (colors_size) {
    case 3 * 2:
        palette_count = 2;
        num_components = 3;
    case 2:
        bits_per_pixel = 1;
        break;
    case 3 * 4:
        palette_count = 4;
        num_components = 3;
    case 4:
        bits_per_pixel = 2;
        break;
    case 3 * 16:
        palette_count = 16;
        num_components = 3;
    case 16:
        bits_per_pixel = 4;
        break;
    case 3 * 256:
        palette_count = 256;
        num_components = 3;
    case 256:
        bits_per_pixel = 8;
        break;
    case -16:
        bits_per_pixel = 16;
        palette_count = 0;
        break;
    case -24:
        bits_per_pixel = 24;
        palette_count = 0;
        break;
    case -32:
        bits_per_pixel = 32;
        palette_count = 0;
        break;
    default:
        return_error(gs_error_rangecheck);
    }
    proto_dev = (word_oriented ?
                 gdev_mem_word_device_for_bits(bits_per_pixel) :
                 gdev_mem_device_for_bits(bits_per_pixel));
    if (proto_dev == 0)		/* no suitable device */
        return_error(gs_error_rangecheck);
    pcount = palette_count * 3;
    /* Check to make sure the palette contains white and black, */
    /* and, if it has any colors, the six primaries. */
    if (bits_per_pixel <= 8) {
        const byte *p;
        byte *q;
        int primary_mask = 0;
        int i;

        has_color = false;
        for (i = 0, p = colors, q = palette;
                i < palette_count; i++, q += 3
            ) {
            int mask = 1;

            switch (num_components) {
            case 1:	/* gray */
                q[0] = q[1] = q[2] = *p++;
                break;
            default /* case 3 */ :		/* RGB */
                q[0] = p[0], q[1] = p[1], q[2] = p[2];
                p += 3;
            }
#define shift_mask(b,n)\
  switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; }
            shift_mask(q[0], 4);
            shift_mask(q[1], 2);
            shift_mask(q[2], 1);
#undef shift_mask
            primary_mask |= mask;
            if (q[0] != q[1] || q[0] != q[2])
                has_color = true;
        }
        switch (primary_mask) {
        case 129:		/* just black and white */
            if (has_color)	/* color but no primaries */
                return_error(gs_error_rangecheck);
        case 255:		/* full color */
            break;
        default:
            return_error(gs_error_rangecheck);
        }
    } else
        has_color = true;
    /*
     * The initial transformation matrix must map 1 user unit to
     * 1/72".  Let W and H be the width and height in pixels, and
     * assume the initial matrix is of the form [A 0 0 B X Y].
     * Then the size of the image in user units is (W/|A|,H/|B|),
     * hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so
     * the number of pixels per inch is
     * (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72).
     * Similarly, if the initial matrix is [0 A B 0 X Y] for a 90
     * or 270 degree rotation, the size of the image in user
     * units is (W/|B|,H/|A|), so the pixels per inch are
     * (|B|*72,|A|*72).  We forbid non-orthogonal transformation
     * matrices.
     */
    if (is_fzero2(pmat->xy, pmat->yx))
        x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy;
    else if (is_fzero2(pmat->xx, pmat->yy))
        x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy;
    else
        return_error(gs_error_undefinedresult);
    /* All checks done, initialize the device. */
    if (bits_per_pixel == 1) {
        /* Determine the polarity from the palette. */
        gs_make_mem_device(new_dev, proto_dev, mem,
                           (page_device ? 1 : -1), 0);
        /* This is somewhat bogus, but does the right thing */
        /* in the only cases we care about. */
        gdev_mem_mono_set_inverted(new_dev,
                                   (palette[0] | palette[1] | palette[2]) != 0);
    } else {
        byte *dev_palette = gs_alloc_string(mem, pcount,
                                            "gs_makeimagedevice(palette)");

        if (dev_palette == 0)
            return_error(gs_error_VMerror);
        gs_make_mem_device(new_dev, proto_dev, mem,
                           (page_device ? 1 : -1), 0);
        new_dev->palette.size = pcount;
        new_dev->palette.data = dev_palette;
        memcpy(dev_palette, palette, pcount);
        if (!has_color) {
            new_dev->color_info.num_components = 1;
            new_dev->color_info.max_color = 0;
            new_dev->color_info.dither_colors = 0;
            new_dev->color_info.gray_index = 0;
        }
    }
    /* Memory defice is always initialised as an internal device but */
    /* this is an external device */
    new_dev->retained = true;
    rc_init(new_dev, new_dev->memory, 1);

    new_dev->initial_matrix = *pmat;
    new_dev->MarginsHWResolution[0] = new_dev->HWResolution[0] =
                                          fabs(x_pixels_per_unit) * 72;
    new_dev->MarginsHWResolution[1] = new_dev->HWResolution[1] =
                                          fabs(y_pixels_per_unit) * 72;
    gx_device_set_width_height((gx_device *) new_dev, width, height);
    /* Set the ImagingBBox so we get a correct clipping region. */
    {
        gs_rect bbox;

        bbox.p.x = 0;
        bbox.p.y = 0;
        bbox.q.x = width;
        bbox.q.y = height;
        gs_bbox_transform_inverse(&bbox, pmat, &bbox);
        new_dev->ImagingBBox[0] = bbox.p.x;
        new_dev->ImagingBBox[1] = bbox.p.y;
        new_dev->ImagingBBox[2] = bbox.q.x;
        new_dev->ImagingBBox[3] = bbox.q.y;
        new_dev->ImagingBBox_set = true;
    }
    /* The bitmap will be allocated when the device is opened. */
    new_dev->is_open = false;
    new_dev->bitmap_memory = mem;
    return 0;
}