- an appropriate visual is selected for the requested Mac color depth

- the list of supported Mac color depths is constructed from the list of
  depth and visuals supported by the X server
This commit is contained in:
cebix 2001-07-06 20:49:53 +00:00
parent e7a13421df
commit 1186b42a20
2 changed files with 212 additions and 97 deletions

View File

@ -237,7 +237,7 @@ static bool video_init_buffer(void)
static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
{
D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
// D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
const uintptr addr = (uintptr)fault_address;
/* Someone attempted to write to the frame buffer. Make it writeable

View File

@ -37,6 +37,12 @@
#include <sys/shm.h>
#include <errno.h>
#include <algorithm>
#ifndef NO_STD_NAMESPACE
using std::sort;
#endif
#ifdef HAVE_PTHREADS
# include <pthread.h>
#endif
@ -116,17 +122,22 @@ static int keycode_table[256]; // X keycode -> Mac keycode translation tabl
// X11 variables
static int screen; // Screen number
static int xdepth; // Depth of X screen
static Window rootwin; // Root window and our window
static XVisualInfo visualInfo;
static Visual *vis;
static Colormap cmap[2] = {0, 0}; // Colormaps for indexed modes (DGA needs two of them)
static int num_depths = 0; // Number of available X depths
static int *avail_depths = NULL; // List of available X depths
static XColor black, white;
static unsigned long black_pixel, white_pixel;
static int eventmask;
static int xdepth; // Depth of X screen
static XVisualInfo visualInfo;
static Visual *vis;
static int color_class;
static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of DirectColor/TrueColor modes
static Colormap cmap[2] = {0, 0}; // Colormaps for indexed modes (DGA needs two of them)
static XColor palette[256]; // Color palette to be used as CLUT and gamma table
static bool palette_changed = false; // Flag: Palette changed, redraw thread must set new colors
@ -192,6 +203,101 @@ static inline uint32 map_rgb(uint8 red, uint8 green, uint8 blue)
return ((red >> rloss) << rshift) | ((green >> gloss) << gshift) | ((blue >> bloss) << bshift);
}
// Do we have a visual for handling the specified Mac depth? If so, set the
// global variables "xdepth", "visualInfo", "vis" and "color_class".
static bool find_visual_for_depth(video_depth depth)
{
D(bug("have_visual_for_depth(%d)\n", 1 << depth));
// Calculate minimum and maximum supported X depth
int min_depth = 1, max_depth = 32;
switch (depth) {
case VDEPTH_1BIT: // 1-bit works always
min_depth = 1;
max_depth = 32;
break;
#ifdef ENABLE_VOSF
case VDEPTH_2BIT:
case VDEPTH_4BIT: // VOSF blitters can convert 2/4-bit -> 16/32-bit
min_depth = 15;
max_depth = 32;
break;
case VDEPTH_8BIT: // VOSF blitters can convert 8-bit -> 16/32-bit
min_depth = 8;
max_depth = 32;
break;
#else
case VDEPTH_2BIT:
case VDEPTH_4BIT: // 2/4-bit requires VOSF blitters
return false;
case VDEPTH_8BIT: // 8-bit without VOSF requires an 8-bit visual
min_depth = 8;
max_depth = 8;
break;
#endif
case VDEPTH_16BIT: // 16-bit requires a 15/16-bit visual
min_depth = 15;
max_depth = 16;
break;
case VDEPTH_32BIT: // 32-bit requires a 24/32-bit visual
min_depth = 24;
max_depth = 32;
break;
}
D(bug(" minimum required X depth is %d, maximum supported X depth is %d\n", min_depth, max_depth));
// Try to find a visual for one of the color depths
bool visual_found = false;
for (int i=0; i<num_depths && !visual_found; i++) {
xdepth = avail_depths[i];
D(bug(" trying to find visual for depth %d\n", xdepth));
if (xdepth < min_depth || xdepth > max_depth)
continue;
// Determine best color class for this depth
switch (xdepth) {
case 1: // Try StaticGray or StaticColor
if (XMatchVisualInfo(x_display, screen, xdepth, StaticGray, &visualInfo)
|| XMatchVisualInfo(x_display, screen, xdepth, StaticColor, &visualInfo))
visual_found = true;
break;
case 8: // Need PseudoColor
if (XMatchVisualInfo(x_display, screen, xdepth, PseudoColor, &visualInfo))
visual_found = true;
break;
case 15:
case 16:
case 24:
case 32: // Try DirectColor first, as this will allow gamma correction
if (XMatchVisualInfo(x_display, screen, xdepth, DirectColor, &visualInfo)
|| XMatchVisualInfo(x_display, screen, xdepth, TrueColor, &visualInfo))
visual_found = true;
break;
default:
D(bug(" not a supported depth\n"));
break;
}
}
if (!visual_found)
return false;
// Visual was found
vis = visualInfo.visual;
color_class = visualInfo.c_class;
D(bug(" found visual ID 0x%02x, depth %d, class ", visualInfo.visualid, xdepth));
#if DEBUG
switch (color_class) {
case StaticGray: D(bug("StaticGray\n")); break;
case GrayScale: D(bug("GrayScale\n")); break;
case StaticColor: D(bug("StaticColor\n")); break;
case PseudoColor: D(bug("PseudoColor\n")); break;
case TrueColor: D(bug("TrueColor\n")); break;
case DirectColor: D(bug("DirectColor\n")); break;
}
#endif
}
// Add mode to list of supported modes
static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth)
{
@ -422,7 +528,7 @@ void driver_base::update_palette(void)
int num = 256;
if (IsDirectMode(VideoMonitor.mode))
num = vis->map_entries; // Palette is gamma table
else if (vis->c_class == DirectColor)
else if (color_class == DirectColor)
return; // Indexed mode on true color screen, don't set CLUT
XStoreColors(x_display, cmap[0], palette, num);
XStoreColors(x_display, cmap[1], palette, num);
@ -450,9 +556,9 @@ driver_window::driver_window(const video_mode &mode)
XSetWindowAttributes wattr;
wattr.event_mask = eventmask = win_eventmask;
wattr.background_pixel = black_pixel;
wattr.colormap = (mode.depth == VDEPTH_1BIT && vis->c_class == PseudoColor ? DefaultColormap(x_display, screen) : cmap[0]);
wattr.colormap = (mode.depth == VDEPTH_1BIT && color_class == PseudoColor ? DefaultColormap(x_display, screen) : cmap[0]);
w = XCreateWindow(x_display, rootwin, 0, 0, width, height, 0, xdepth,
InputOutput, vis, CWEventMask | CWBackPixel | (vis->c_class == PseudoColor || vis->c_class == DirectColor ? CWColormap : 0), &wattr);
InputOutput, vis, CWEventMask | CWBackPixel | (color_class == PseudoColor || color_class == DirectColor ? CWColormap : 0), &wattr);
// Set window name/class
set_window_name(w, STR_WINDOW_TITLE);
@ -1139,14 +1245,54 @@ static void keycode_init(void)
// Open display for specified mode
static bool video_open(const video_mode &mode)
{
// Find best available X visual
if (!find_visual_for_depth(mode.depth)) {
ErrorAlert(STR_NO_XVISUAL_ERR);
return false;
}
// Create color maps
if (color_class == PseudoColor || color_class == DirectColor) {
cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll);
}
// Find pixel format of direct modes
if (color_class == DirectColor || color_class == TrueColor) {
rshift = gshift = bshift = 0;
rloss = gloss = bloss = 8;
uint32 mask;
for (mask=vis->red_mask; !(mask&1); mask>>=1)
++rshift;
for (; mask&1; mask>>=1)
--rloss;
for (mask=vis->green_mask; !(mask&1); mask>>=1)
++gshift;
for (; mask&1; mask>>=1)
--gloss;
for (mask=vis->blue_mask; !(mask&1); mask>>=1)
++bshift;
for (; mask&1; mask>>=1)
--bloss;
}
// Preset palette pixel values for gamma table
if (color_class == DirectColor) {
int num = vis->map_entries;
for (int i=0; i<num; i++) {
int c = (i * 256) / num;
palette[i].pixel = map_rgb(c, c, c);
}
}
// Load gray ramp to color map
int num = (vis->c_class == DirectColor ? vis->map_entries : 256);
int num = (color_class == DirectColor ? vis->map_entries : 256);
for (int i=0; i<num; i++) {
int c = (i * 256) / num;
palette[i].red = c * 0x0101;
palette[i].green = c * 0x0101;
palette[i].blue = c * 0x0101;
if (vis->c_class == PseudoColor)
if (color_class == PseudoColor)
palette[i].pixel = i;
palette[i].flags = DoRed | DoGreen | DoBlue;
}
@ -1157,7 +1303,7 @@ static bool video_open(const video_mode &mode)
#ifdef ENABLE_VOSF
// Load gray ramp to 8->16/32 expand map
if (!IsDirectMode(mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor))
if (!IsDirectMode(mode) && (color_class == TrueColor || color_class == DirectColor))
for (int i=0; i<256; i++)
ExpandMap[i] = map_rgb(i, i, i);
#endif
@ -1249,9 +1395,14 @@ bool VideoInit(bool classic)
// Find screen and root window
screen = XDefaultScreen(x_display);
rootwin = XRootWindow(x_display, screen);
// Get screen depth
xdepth = DefaultDepth(x_display, screen);
// Get sorted list of available depths
avail_depths = XListDepths(x_display, screen, &num_depths);
if (avail_depths == NULL) {
ErrorAlert(STR_UNSUPP_DEPTH_ERR);
return false;
}
sort(avail_depths, avail_depths + num_depths);
#ifdef ENABLE_FBDEV_DGA
// Frame buffer name
@ -1291,71 +1442,6 @@ bool VideoInit(bool classic)
black_pixel = BlackPixel(x_display, screen);
white_pixel = WhitePixel(x_display, screen);
// Get appropriate visual
int color_class;
switch (xdepth) {
case 1:
color_class = StaticGray;
break;
case 8:
color_class = PseudoColor;
break;
case 15:
case 16:
case 24:
case 32: // Try DirectColor first, as this will allow gamma correction
color_class = DirectColor;
if (!XMatchVisualInfo(x_display, screen, xdepth, color_class, &visualInfo))
color_class = TrueColor;
break;
default:
ErrorAlert(STR_UNSUPP_DEPTH_ERR);
return false;
}
if (!XMatchVisualInfo(x_display, screen, xdepth, color_class, &visualInfo)) {
ErrorAlert(STR_NO_XVISUAL_ERR);
return false;
}
if (visualInfo.depth != xdepth) {
ErrorAlert(STR_NO_XVISUAL_ERR);
return false;
}
vis = visualInfo.visual;
// Create color maps
if (color_class == PseudoColor || color_class == DirectColor) {
cmap[0] = XCreateColormap(x_display, rootwin, vis, AllocAll);
cmap[1] = XCreateColormap(x_display, rootwin, vis, AllocAll);
}
// Find pixel format of direct modes
if (color_class == DirectColor || color_class == TrueColor) {
rshift = gshift = bshift = 0;
rloss = gloss = bloss = 8;
uint32 mask;
for (mask=vis->red_mask; !(mask&1); mask>>=1)
++rshift;
for (; mask&1; mask>>=1)
--rloss;
for (mask=vis->green_mask; !(mask&1); mask>>=1)
++gshift;
for (; mask&1; mask>>=1)
--gloss;
for (mask=vis->blue_mask; !(mask&1); mask>>=1)
++bshift;
for (; mask&1; mask>>=1)
--bloss;
}
// Preset palette pixel values for gamma table
if (color_class == DirectColor) {
int num = vis->map_entries;
for (int i=0; i<num; i++) {
int c = (i * 256) / num;
palette[i].pixel = map_rgb(c, c, c);
}
}
// Get screen mode from preferences
const char *mode_str;
if (classic_mode)
@ -1390,28 +1476,51 @@ bool VideoInit(bool classic)
default_height = DisplayHeight(x_display, screen);
// Mac screen depth follows X depth
video_depth default_depth = DepthModeForPixelDepth(xdepth);
video_depth default_depth = VDEPTH_1BIT;
switch (DefaultDepth(x_display, screen)) {
case 8:
default_depth = VDEPTH_8BIT;
break;
case 15: case 16:
default_depth = VDEPTH_16BIT;
break;
case 24: case 32:
default_depth = VDEPTH_32BIT;
break;
}
// Construct list of supported modes
if (display_type == DISPLAY_WINDOW) {
if (classic)
add_mode(512, 342, 0x80, 64, VDEPTH_1BIT);
else {
if (default_depth != VDEPTH_1BIT)
add_window_modes(VDEPTH_1BIT); // 1-bit modes are always available
#ifdef ENABLE_VOSF
if (default_depth > VDEPTH_8BIT) {
add_window_modes(VDEPTH_2BIT); // 2, 4 and 8-bit modes are also possible on 16/32-bit screens with VOSF blitters
add_window_modes(VDEPTH_4BIT);
add_window_modes(VDEPTH_8BIT);
for (unsigned d=VDEPTH_1BIT; d<=VDEPTH_32BIT; d++) {
if (find_visual_for_depth(video_depth(d)))
add_window_modes(video_depth(d));
}
#endif
add_window_modes(default_depth);
}
} else
add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth);
if (VideoModes.empty()) {
ErrorAlert(STR_NO_XVISUAL_ERR);
return false;
}
video_init_depth_list();
#if DEBUG
D(bug("Available video modes:\n"));
vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
while (i != end) {
int bits = 1 << i->depth;
if (bits == 16)
bits = 15;
else if (bits == 32)
bits = 24;
D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits));
++i;
}
#endif
// Find requested default mode and open display
if (VideoModes.size() == 1)
return video_open(VideoModes[0]);
@ -1467,12 +1576,6 @@ static void video_close(void)
// Close display
delete drv;
drv = NULL;
}
void VideoExit(void)
{
// Close display
video_close();
// Free colormaps
if (cmap[0]) {
@ -1483,6 +1586,12 @@ void VideoExit(void)
XFreeColormap(x_display, cmap[1]);
cmap[1] = 0;
}
}
void VideoExit(void)
{
// Close display
video_close();
#ifdef ENABLE_XF86_VIDMODE
// Free video mode list
@ -1499,6 +1608,12 @@ void VideoExit(void)
fbdev_fd = -1;
}
#endif
// Free depth list
if (avail_depths) {
XFree(avail_depths);
avail_depths = NULL;
}
}
@ -1550,7 +1665,7 @@ void video_set_palette(uint8 *pal, int num_in)
p->red = pal[c*3 + 0] * 0x0101;
p->green = pal[c*3 + 1] * 0x0101;
p->blue = pal[c*3 + 2] * 0x0101;
if (vis->c_class == PseudoColor)
if (color_class == PseudoColor)
p->pixel = i;
p->flags = DoRed | DoGreen | DoBlue;
p++;
@ -1558,7 +1673,7 @@ void video_set_palette(uint8 *pal, int num_in)
#ifdef ENABLE_VOSF
// Recalculate pixel color expansion map
if (!IsDirectMode(VideoMonitor.mode) && (vis->c_class == TrueColor || vis->c_class == DirectColor)) {
if (!IsDirectMode(VideoMonitor.mode) && (color_class == TrueColor || color_class == DirectColor)) {
for (int i=0; i<256; i++) {
int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier)
ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]);