#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: grfabs.c,v 1.20 2023/12/20 00:40:42 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/queue.h>
#include <machine/cpu.h>
#include <machine/iomap.h>
#include <machine/video.h>
#include <machine/mfp.h>
#include <atari/dev/grfabs_reg.h>
static dmode_t *get_best_display_mode(dimen_t *, int, dmode_t *);
static MODES modes;
view_t gra_con_view;
colormap_t gra_con_cmap;
long gra_con_colors[MAX_CENTRIES];
u_long gra_def_color16[16] = {
0x00000000,
0x00ffffff,
0x000c0c0c,
0x00808008,
0x0000000c,
0x00000c00,
0x00000c0c,
0x00c00000,
0x00c0000c,
0x00c00c00,
0x000000ff,
0x0000ff00,
0x0000ffff,
0x00ff0000,
0x00ff00ff,
0x00ffff00
};
int
grfabs_probe(grf_probe_t probe_fun)
{
static int inited = 0;
if (!inited) {
LIST_INIT(&modes);
inited = 1;
}
(*probe_fun)(&modes);
return ((modes.lh_first == NULL) ? 0 : 1);
}
view_t *
grf_alloc_view(dmode_t *d, dimen_t *dim, u_char depth)
{
if (!d)
d = get_best_display_mode(dim, depth, NULL);
if (d)
return ((d->grfabs_funcs->alloc_view)(d, dim, depth));
return(NULL);
}
dmode_t *
grf_get_best_mode(dimen_t *dim, u_char depth)
{
return (get_best_display_mode(dim, depth, NULL));
}
void
grf_display_view(view_t *v)
{
(v->mode->grfabs_funcs->display_view)(v);
}
void
grf_remove_view(view_t *v)
{
(v->mode->grfabs_funcs->remove_view)(v);
}
void
grf_save_view(view_t *v)
{
(v->mode->grfabs_funcs->save_view)(v);
}
void
grf_free_view(view_t *v)
{
(v->mode->grfabs_funcs->free_view)(v);
}
int
grf_get_colormap(view_t *v, colormap_t *cm)
{
colormap_t *gcm;
int i, n;
u_long *sv_entry;
gcm = v->colormap;
n = cm->size < gcm->size ? cm->size : gcm->size;
sv_entry = cm->entry;
*cm = *gcm;
cm->entry = sv_entry;
memset(cm->entry, 0, cm->size * sizeof(long));
for (i = 0; i < n; i++)
cm->entry[i] = gcm->entry[i];
return (0);
}
int
grf_use_colormap(view_t *v, colormap_t *cm)
{
return (v->mode->grfabs_funcs->use_colormap)(v, cm);
}
static dmode_t *
get_best_display_mode(dimen_t *dim, int depth, dmode_t *curr_mode)
{
dmode_t *save;
dmode_t *dm;
long dx, dy, dd, ct;
long size_diff, depth_diff;
save = NULL;
size_diff = 0;
depth_diff = 0;
dm = modes.lh_first;
while (dm != NULL) {
dx = abs(dm->size.width - dim->width);
dy = abs(dm->size.height - dim->height);
dd = abs(dm->depth - depth);
ct = dx + dy;
if ((save != NULL) && (size_diff == 0)) {
if (dd > depth_diff) {
dm = dm->link.le_next;
continue;
}
}
if ((save == NULL) || (ct <= size_diff)) {
save = dm;
size_diff = ct;
depth_diff = dd;
}
dm = dm->link.le_next;
}
if ((save != NULL) && (curr_mode != NULL)) {
dx = abs(curr_mode->size.width - dim->width);
dy = abs(curr_mode->size.height - dim->height);
dd = abs(curr_mode->depth - depth);
ct = dx + dy;
if ((ct <= size_diff) && (dd <= depth_diff))
return (NULL);
}
return (save);
}