#ifndef lint #ifdef sccs static char sccsid[] = "@(#)pw_cms.c 1.1 94/10/31 Copyr 1986 Sun Micro"; #endif #endif /* * Copyright (c) 1986 by Sun Microsystems, Inc. */ /* * Pw_cms.c: Implement the colormap segment sharing aspect of * the pixwin.h interface. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef PRE_IBIS #include #endif extern char *sprintf(); static void pw_set_plane_group(); static void pw_set_planes_limited(); extern int errno; static cmsid; int pwenforcecmstd; /* Leave in case old program touching */ /* Not used anymore */ #define NO_PLANE_PTR ((int *)0) struct colormapseg pw_defaultcms; u_char pw_defaultred[256]; u_char pw_defaultgreen[256]; u_char pw_defaultblue[256]; struct cms_map pw_defaultmap = { pw_defaultred, pw_defaultgreen, pw_defaultblue}; static int pw_plane_group_preference_set; static int pw_plane_group_preference; static int pw_global_groups_available_set; static struct win_plane_groups_available pw_global_groups_available; static void pw_read_plane_group_preference(); static void pw_initialize_plane_group(); static void pw_initialize_invisible_pg(); static int pw_choose_prefered_plane_group(); #ifndef PRE_FLAMINGO static void fullscreen_pw_start_plane_group_loop(); static int fullscreen_pw_next_plane_group(); static void fullscreen_pw_finish_plane_group(); #endif static int fullscreen_pw_start_other_plane_group(); static void fullscreen_pw_finish_other_plane_group(); void pw_set_planes_directly(); void win_set_plane_group(); int win_get_plane_group(); void pw_use_fast_monochrome(); void pw_use_color24(); /* * Colormap segment manager operations. */ pw_setcmsname(pw, cmsname) struct pixwin *pw; char *cmsname; { if (strncmp(pw->pw_cmsname, cmsname, CMS_NAMESIZE) != 0) { (void)win_clearcms(pw->pw_clipdata->pwcd_windowfd); (void)strncpy(pw->pw_cmsname, cmsname, CMS_NAMESIZE); #ifndef PRE_IBIS /* If the user tries to switch to a monochrome colormap segment, the window should no longer reside in the 24 bit planes. Question: Need to change plane groups here? This routine is called from tool_setgroundcolor () in libsuntool/tool/tla_set.c. */ if (0 == strncmp (cmsname, CMS_MONOCHROME, CMS_NAMESIZE)) pw->pw_clipdata->pwcd_flags &= ~PWCD_COLOR24; #endif ndef PRE_IBIS } } pw_getcmsname(pw, cmsname) struct pixwin *pw; char *cmsname; { (void)strncpy(cmsname, pw->pw_cmsname, CMS_NAMESIZE); } pwo_putattributes(pw, planes) struct pixwin *pw; register int *planes; { struct colormapseg cms; int myplanes; int firstplanes; if (!planes) return(0); (void)pw_getcmsdata(pw, &cms, &firstplanes); if (cms.cms_size < 256) if (pw->pw_clipdata->pwcd_flags & PWCD_SET_CMAP_SIZE) { /* * restrict the mask to one less than the next power of 2 * greater or equal than the size of the cmap */ int mask; for (mask = 1; mask <= cms.cms_size; mask <<= 1); myplanes = *planes & mask - 1; } else myplanes = *planes & cms.cms_size - 1; else myplanes = *planes & PIX_ALL_PLANES; /* Put planes in pixrect for protection */ #ifdef planes_fully_implemented pr_putattributes(pw->pw_pixrect, &myplanes); #else (void)pw_full_putattributes(pw->pw_pixrect, &myplanes); #endif planes_fully_implemented /* Reset clipping to get changes to clipping pixrects */ if (firstplanes != myplanes) (void)pw_getclipping(pw); return(0); } pwo_getattributes(pw, planes) struct pixwin *pw; int *planes; { return(pr_getattributes(pw->pw_pixrect, planes)); } /* * Will inherit screen inversion in single plane case. * Will initialize planes offset so that think are * writing to zero offset in multi-plane case. */ pwo_putcolormap(pw, idx, count, red, green, blue) register Pixwin *pw; int idx, count; u_char red[], green[], blue[]; { struct colormapseg cms; struct cms_map cmap; int planes; int new_cms, base_pixrect_changed = 0; /* Determine status of cms */ (void)pw_getcmsdata(pw, &cms, NO_PLANE_PTR); /* See if changing cms */ new_cms = (strncmp(cms.cms_name, pw->pw_cmsname, CMS_NAMESIZE) != 0); /* * If pw_cmsname is not set then generate a unique name. * Obviously, this cms will not be shared. */ if (pw->pw_cmsname[0] == '\0') (void)sprintf(pw->pw_cmsname, "cms%10ld-%4ld", getpid(), cmsid++); /* * If changing colormap segments, maybe changing plane group. */ if (new_cms) { int original_plane_group, new_plane_group; /* * Choose plane group based on new cms name, user * preference and availability of plane groups. */ new_plane_group = pw_choose_prefered_plane_group(pw, &original_plane_group); /* Tell kernel about this window's plane group */ win_set_plane_group(pw->pw_windowfd, new_plane_group); /* * Put plane group in pixrect (got original_plane_group * from pixrect). */ if (original_plane_group != new_plane_group) pw_set_plane_group(pw, new_plane_group); /* * new_cms flag will cause change to pixrect to * be propagated to other pixrects in pixwin. */ } /* * Set the cms in the kernel using cmsname. * Kernel recognizes size<(original size) &| offset != 0 to be partial * cmap updates. */ cms.cms_addr = idx; cms.cms_size = count; (void)strncpy(cms.cms_name, pw->pw_cmsname, CMS_NAMESIZE); cmap.cm_red = red; cmap.cm_green = green; cmap.cm_blue = blue; (void)win_setcms(pw->pw_clipdata->pwcd_windowfd, &cms, &cmap); { /* * Indexed emulation in a true-color environment needs * some pw_colormap information. */ int win_fd; win_fd = (strcmp(cms.cms_name, CMS_MONOCHROME)) ? pw->pw_clipdata->pwcd_windowfd : -2; (void) pr_ioctl(pw->pw_pixrect, FBIOSWINFD, &win_fd); (void) pr_ioctl(pw->pw_pixrect, FBIOSCMS, &cms); } /* * Propagate actual color change. */ /* Clear shared locking inversion flag */ pw->pw_clipdata->pwcd_flags &= ~PWCD_CURSOR_INVERTED; if (pw->pw_pixrect->pr_depth == 1) { u_char rbefore[2], g[2], b[2], rafter[2]; struct screen screen; (void)pr_getcolormap(pw->pw_pixrect, 0, 2, rbefore, g, b); /* * One tells monochrome displays about being reversed * by doing a pr_putcolormap (although no colormap is modified). * Bws also don't use the planes attribute. */ (void)pr_putcolormap(pw->pw_pixrect, idx, count, red, green, blue); (void)pr_getcolormap(pw->pw_pixrect, 0, 2, rafter, g, b); /* * The zero entry of red controls the reverse mode on monochrome * devices. See if changed. */ if (rbefore[0] != rafter[0]) base_pixrect_changed = 1; /* set the revers-relative-to-kernel bit for cursor rops */ (void)win_screenget(pw->pw_windowfd, &screen); if (((screen.scr_background.red == rafter[0]) && (screen.scr_flags & SCR_SWITCHBKGRDFRGRD)) || ((screen.scr_background.red != rafter[0]) && (!(screen.scr_flags & SCR_SWITCHBKGRDFRGRD)))) pw->pw_clipdata->pwcd_flags |= PWCD_CURSOR_INVERTED; } else { if (new_cms) { /* Put planes in pixrect for offset protection */ if (cms.cms_size < 256) if (pw->pw_clipdata->pwcd_flags & PWCD_SET_CMAP_SIZE) { /* * set the mask to one less than the next power of * 2 greater or equal than the size of the cmap */ int mask; for (mask = 1; mask <= cms.cms_size; mask <<= 1); planes = mask - 1; } else planes = cms.cms_size - 1; else planes = PIX_ALL_PLANES; #ifdef planes_fully_implemented pr_putattributes(pw->pw_pixrect, &planes); #else (void)pw_full_putattributes(pw->pw_pixrect, &planes); #endif planes_fully_implemented } /* else used to AND with previous planes * in case user has restricted planes already * but this should be a no-op so removed this code. */ } /* * If changing colormap size, retained image may need to be * reallocated. */ if (new_cms && pw->pw_prretained) (void)pw_set_retain(pw, pw->pw_prretained->pr_width, pw->pw_prretained->pr_height); /* * Recompute clippers so that all accessing pixrects * are the same if change base pixrect or have new cms. */ if (base_pixrect_changed || new_cms) (void)pw_getclipping(pw); /* * Prepare surface of entire visible area of the pixwin. */ if (new_cms) (void)pw_preparesurface_full(pw, RECT_NULL, 1); return(0); } pwo_getcolormap(pw, idx, count, red, green, blue) struct pixwin *pw; int idx, count; u_char red[], green[], blue[]; { struct colormapseg cms; struct cms_map cmap; /* * If pw_cmsname is not set then error. */ if (pw->pw_cmsname[0] == '\0') { (void)fprintf(stderr, "pw_cmsname NULL in getcolormap\n"); return(EINVAL); } /* * Get cms from window system. */ cms.cms_addr = idx; cms.cms_size = count; (void)strncpy(cms.cms_name, pw->pw_cmsname, CMS_NAMESIZE); cmap.cm_red = red; cmap.cm_green = green; cmap.cm_blue = blue; (void)win_getcms(pw->pw_clipdata->pwcd_windowfd, &cms, &cmap); /* * Internal check. */ if (strncmp(pw->pw_cmsname, cms.cms_name, CMS_NAMESIZE) != 0) { (void)fprintf(stderr, "cms names differ in pw_getcolormap\n"); return(EINVAL); } return(0); } pw_preparesurface(pw, rect) register Pixwin *pw; struct rect *rect; { (void)pw_preparesurface_full(pw, rect, 0); } pw_preparesurface_full(pw, rect, full) register Pixwin *pw; struct rect *rect; int full; { struct rect rdest; struct colormapseg cms; char *plane_groups_available = pw->pw_clipdata->pwcd_plane_groups_available; int plane_group; int pw_dbl_wrstate; /* See if some other pixwin on this window changed the cms */ (void)pw_getcmsdata(pw, &cms, NO_PLANE_PTR); if (strncmp(pw->pw_cmsname, cms.cms_name, CMS_NAMESIZE) != 0) { /* Get current cms/planes of window for this pixwin */ (void)pw_initcms(pw); /* Update cms variable */ (void)pw_getcmsdata(pw, &cms, NO_PLANE_PTR); } /* Supply rdest if rect not supplied. Restrict to visible area. */ if (rect) (void)rect_intersection(&pw->pw_clipdata->pwcd_clipping.rl_bound, rect, &rdest); else rdest = pw->pw_clipdata->pwcd_clipping.rl_bound; /* See if anything to do */ if (rect_isnull(&rdest)) /* Assumes no side affects from calling this routine */ return; /* See if some other pixwin on this window changed the plane group */ if (plane_groups_available[PIXPG_OVERLAY_ENABLE] || plane_groups_available[PIXPG_VIDEO_ENABLE] || plane_groups_available[PIXPG_WID]) { /* NOTE: ADD HERE AS NEW ENABLE PLANES BECOME AVAILABLE */ /* Get this window's choice of planes from kernel */ plane_group = win_get_plane_group(pw->pw_windowfd, pw->pw_pixrect); if (plane_group != pw->pw_clipdata->pwcd_plane_group) { /* Get current cms/planes of window for this pixwin */ (void)pw_initcms(pw); /* Update plane_group variable */ plane_group = win_get_plane_group(pw->pw_windowfd, pw->pw_pixrect); } } /* * Get the state of the double buffering when there is no * fullscreen access. Set write to both. */ if ((pw->pw_clipdata->pwcd_flags & PWCD_DBL_AVAIL) && !(pw->pw_clipdata->pwcd_flags & PWCD_IGNORE_DBLSET)) { pw_dbl_wrstate = pw_dbl_get(pw, PW_DBL_WRITE); pw_dbl_set(pw, PW_DBL_WRITE, PW_DBL_BOTH, 0); } /* Remove cursor for duration of preparation */ (void)pw_lock(pw, &rdest); /* * Enable bits that program will be writing to. * Do before enable planes to avoid "ghost" image flashes. */ if (pw->pw_pixrect->pr_depth > 1 || plane_groups_available[PIXPG_OVERLAY_ENABLE] || plane_groups_available[PIXPG_VIDEO_ENABLE] || plane_groups_available[PIXPG_WID]) { /* NOTE: ADD HERE AS NEW ENABLE PLANES BECOME AVAILABLE */ /* Prepare depth > 1 pixwin's surface */ if ((pw->pw_clipdata->pwcd_flags & (PWCD_COLOR24|PWCD_VIDEO)) != (PWCD_COLOR24|PWCD_VIDEO) ) { pw_initialize_plane_group(pw, pr_get_plane_group(pw->pw_pixrect), (pw->pw_clipdata->pwcd_flags & PWCD_COLOR24) ? 0 : cms.cms_addr, &rdest); } } /* * else simple 1 deep pixwins clear own areas so don't prepare * surface because pixwins are supposed to clear (or set) their * own surfaces anyway. */ /* * The enable plane and other invisible plane groups are initialized * here. Do the "other" invisible plane groups last so as to not * slow down the preceived repaint speed so much. */ if (plane_groups_available[PIXPG_OVERLAY_ENABLE] || plane_groups_available[PIXPG_VIDEO_ENABLE] || plane_groups_available[PIXPG_WID]) { /* NOTE: ADD HERE AS NEW ENABLE PLANES BECOME AVAILABLE */ switch (plane_group) { case PIXPG_8BIT_COLOR: if (plane_groups_available[PIXPG_OVERLAY_ENABLE]) { pw_initialize_invisible_pg(pw, PIXPG_OVERLAY_ENABLE, 0, &rdest, plane_group); } if (plane_groups_available[PIXPG_VIDEO_ENABLE]) { pw_initialize_invisible_pg(pw, PIXPG_VIDEO_ENABLE, 0, &rdest, plane_group); } if (full && plane_groups_available[PIXPG_OVERLAY]) { pw_initialize_invisible_pg(pw, PIXPG_OVERLAY, 0, &rdest, plane_group); } if (plane_groups_available[PIXPG_WID]) { struct fb_wid_dbl_info w; ioctl(pw->pw_windowfd, WINWIDGET, &w); if (w.dbl_wid.wa_count == 0) { w.dbl_wid.wa_index = -1; w.dbl_wid.wa_type = FB_WID_SHARED_8; w.dbl_wid.wa_count = 1; pr_ioctl(pw->pw_pixrect,FBIO_WID_ALLOC, &w.dbl_wid); ioctl(pw->pw_windowfd, WINWIDSET, &w); } pw_initialize_invisible_pg(pw, PIXPG_WID, w.dbl_wid.wa_index, &rdest, plane_group); } break; case PIXPG_OVERLAY: pw_initialize_invisible_pg(pw, PIXPG_OVERLAY_ENABLE, 1, &rdest, plane_group); if (plane_groups_available[PIXPG_VIDEO_ENABLE]) { pw_initialize_invisible_pg(pw, PIXPG_VIDEO_ENABLE, 0, &rdest, plane_group); } if (full) { if (plane_groups_available[PIXPG_8BIT_COLOR] ) { pw_initialize_invisible_pg(pw, PIXPG_8BIT_COLOR, 0, &rdest, plane_group); } if (plane_groups_available[PIXPG_24BIT_COLOR] ) { pw_initialize_invisible_pg(pw, PIXPG_24BIT_COLOR, 0, &rdest, plane_group); } } break; case PIXPG_24BIT_COLOR: if (plane_groups_available[PIXPG_OVERLAY_ENABLE]) pw_initialize_invisible_pg(pw, PIXPG_OVERLAY_ENABLE, 0, &rdest, plane_group); if (plane_groups_available[PIXPG_VIDEO_ENABLE]) { pw_initialize_invisible_pg(pw, PIXPG_VIDEO_ENABLE, pw->pw_clipdata->pwcd_flags & PWCD_VIDEO ? 1: 0, &rdest, plane_group); } /* On 24 Bit frame buffers (cg8, cg9, cg12), both the * enable and the * overlay must be cleared in order for the 24 bit * color plane to show through */ if (plane_groups_available[PIXPG_OVERLAY_ENABLE]) pw_initialize_invisible_pg(pw, PIXPG_OVERLAY, 0, &rdest, plane_group); if (plane_groups_available[PIXPG_WID]) { struct fb_wid_dbl_info w; ioctl(pw->pw_windowfd, WINWIDGET, &w); /* If someone sets CANVAS24 to true AFTER * initial canvas creation you could get here * with the current wid of an 8bit type !! */ if ((w.dbl_wid.wa_count == 0) || (w.dbl_wid.wa_type == FB_WID_SHARED_8) || (w.dbl_wid.wa_type == FB_WID_DBL_8)) { w.dbl_wid.wa_index = -1; w.dbl_wid.wa_type = FB_WID_SHARED_24; w.dbl_wid.wa_count = 1; pr_ioctl(pw->pw_pixrect,FBIO_WID_ALLOC, &w.dbl_wid); ioctl(pw->pw_windowfd, WINWIDSET, &w); } pw_initialize_invisible_pg(pw, PIXPG_WID, w.dbl_wid.wa_index, &rdest, plane_group); } break; case PIXPG_VIDEO: pw_initialize_invisible_pg(pw, PIXPG_VIDEO_ENABLE, 1, &rdest, plane_group); if (full) { if (plane_groups_available[PIXPG_OVERLAY_ENABLE]) { pw_initialize_invisible_pg(pw, PIXPG_OVERLAY_ENABLE, 1, &rdest, plane_group); } if (plane_groups_available[PIXPG_8BIT_COLOR]) { pw_initialize_invisible_pg(pw, PIXPG_8BIT_COLOR, 255, &rdest, plane_group); } if (plane_groups_available[PIXPG_OVERLAY]) { pw_initialize_invisible_pg(pw, PIXPG_OVERLAY, 1, &rdest, plane_group); } if (plane_groups_available [PIXPG_24BIT_COLOR]) { pw_initialize_invisible_pg (pw, PIXPG_24BIT_COLOR, 0, &rdest, plane_group); } } break; default: /* * Nop. One can get into this situation if this * routine gets called recursively during damage * repair. The affect of ignoring this is that * surface preparation occasionally gets done twice, * which is OK. * * More explicitly: * pw_preparesurface_full() here we are * pw_damaged() * pwco_lockstd() * pw_initialize_plane_group() * pw_initialize_invisible_pg() * pw_preparesurface_full() above here * pw_damaged() * ... */ break; } } /* * Reinstate the write control bit */ if ((pw->pw_clipdata->pwcd_flags & PWCD_DBL_AVAIL) && !(pw->pw_clipdata->pwcd_flags & PWCD_IGNORE_DBLSET)) { pw_dbl_set(pw, PW_DBL_WRITE, pw_dbl_wrstate, 0); } /* Replace cursor */ (void)pw_unlock(pw); return; } pw_blackonwhite( pw, first, last) struct pixwin *pw; int first, last; { unsigned char black = 0, white = -1; (void)pw_setgrnd(pw, first, last, black, black, black, white, white, white); } pw_whiteonblack( pw, first, last) struct pixwin *pw; int first, last; { unsigned char black = 0, white = -1; (void)pw_setgrnd(pw, first, last, white, white, white, black, black, black); } pw_reversevideo( pw, first, last) struct pixwin *pw; int first, last; { struct screen screen; (void)win_screenget(pw->pw_clipdata->pwcd_windowfd, &screen); (void)pw_setgrnd(pw, first, last, screen.scr_background.red, screen.scr_background.green, screen.scr_background.blue, screen.scr_foreground.red, screen.scr_foreground.green, screen.scr_foreground.blue); } pw_setdefaultcms(cms, map) struct colormapseg *cms; struct cms_map *map; { if (cms->cms_size > 256) return(-1); pw_defaultcms = *cms; bcopy((caddr_t)map->cm_red, (caddr_t)pw_defaultmap.cm_red, cms->cms_size); bcopy((caddr_t)map->cm_green, (caddr_t)pw_defaultmap.cm_green, cms->cms_size); bcopy((caddr_t)map->cm_blue, (caddr_t)pw_defaultmap.cm_blue, cms->cms_size); return(0); } pw_getdefaultcms(cms, map) struct colormapseg *cms; struct cms_map *map; { if (cms->cms_size < pw_defaultcms.cms_size || pw_defaultcms.cms_size == 0) return(-1); *cms = pw_defaultcms; bcopy((caddr_t)pw_defaultmap.cm_red, (caddr_t)map->cm_red, pw_defaultcms.cms_size); bcopy((caddr_t)pw_defaultmap.cm_green, (caddr_t)map->cm_green, pw_defaultcms.cms_size); bcopy((caddr_t)pw_defaultmap.cm_blue, (caddr_t)map->cm_blue, pw_defaultcms.cms_size); return(0); } /* * Newly Public routines: */ struct pixwin * pw_open_monochrome(windowfd) int windowfd; { struct pixwin *pw = pw_open(windowfd); if (pw) pw_use_fast_monochrome(pw); return (pw); } void pw_use_fast_monochrome(pw) register Pixwin *pw; { /* Use overlay plane for monochrome cms (if overlay is available) */ #ifdef PRE_IBIS if (pw->pw_clipdata->pwcd_plane_group == PIXPG_8BIT_COLOR && strncmp(pw->pw_cmsname, CMS_MONOCHROME, CMS_NAMESIZE) == 0 && (pw->pw_clipdata->pwcd_plane_groups_available[PIXPG_OVERLAY])) { #else ndef PRE_IBIS if ((pw->pw_clipdata->pwcd_plane_group == PIXPG_8BIT_COLOR || pw->pw_clipdata->pwcd_plane_group == PIXPG_24BIT_COLOR) && strncmp(pw->pw_cmsname, CMS_MONOCHROME, CMS_NAMESIZE) == 0 && pw->pw_clipdata->pwcd_plane_groups_available [PIXPG_OVERLAY]) { #endif else ndef PRE_IBIS win_set_plane_group(pw->pw_windowfd, PIXPG_OVERLAY); pw_set_planes_directly(pw, PIXPG_OVERLAY, PIX_ALL_PLANES); pw->pw_cmsname[0] = NULL; /* Forces call to pw_initcms */ (void)pw_preparesurface_full(pw, RECT_NULL, 1); } } #ifndef PRE_IBIS struct pixwin * pw_open_color24(windowfd) int windowfd; { struct pixwin *pw = pw_open(windowfd); if (pw) pw_use_color24(pw); return (pw); } void pw_use_color24(pw) register Pixwin *pw; { /* Use 24 bit plane group for color24 cms (if PG_24BIT_COLOR is available) */ if (pw->pw_clipdata->pwcd_plane_groups_available [PIXPG_24BIT_COLOR]) { pw->pw_clipdata->pwcd_flags |= PWCD_COLOR24; win_set_plane_group(pw->pw_windowfd, PIXPG_24BIT_COLOR); pw_set_planes_directly(pw, PIXPG_24BIT_COLOR, PIX_ALL_PLANES); pw->pw_cmsname[0] = NULL; /* Forces call to pw_initcms */ if (pw->pw_prretained) pw_set_retain(pw, pw->pw_prretained->pr_size.x, pw->pw_prretained->pr_size.y); (void)pw_preparesurface_full(pw, RECT_NULL, 1); } } #endif ndef PRE_IBIS #ifndef PRE_FLAMINGO struct pixwin * pw_open_video(windowfd) int windowfd; { struct pixwin *pw = pw_open(windowfd); if (pw) (void)pw_use_video(pw); return (pw); } struct pixwin * pw_use_video(pw) register Pixwin *pw; { /* Use video plane group */ if (pw->pw_clipdata->pwcd_plane_groups_available[PIXPG_VIDEO] && TRUE /* need to check if already in use on another pw */) { pw->pw_clipdata->pwcd_flags |= PWCD_VIDEO; win_set_plane_group(pw->pw_windowfd, PIXPG_VIDEO); pw_set_planes_directly(pw, PIXPG_VIDEO, PIX_ALL_PLANES); pw->pw_cmsname[0] = NULL; /* Forces call to pw_initcms */ (void)pw_preparesurface_full(pw, RECT_NULL, 1); return (pw); } else return (NULL); } #endif ndef PRE_FLAMINGO void pw_set_plane_group_preference(plane_group) int plane_group; { pw_plane_group_preference = plane_group; pw_plane_group_preference_set = 1; } int pw_get_plane_group_preference() { return (pw_plane_group_preference); } /* * Semi-public routines: */ pw_getcmsdata(pw, cms, planes) struct pixwin *pw; struct colormapseg *cms; int *planes; { struct cms_map cmap; if (planes != NO_PLANE_PTR) (void)pr_getattributes(pw->pw_pixrect, planes); /* * Get the truth from the kernel */ cmap.cm_red = cmap.cm_green = cmap.cm_blue = 0; (void)win_getcms(pw->pw_clipdata->pwcd_windowfd, cms, &cmap); } /* * Newly Semi-public routines: */ int win_get_plane_group(windowfd, pr) int windowfd; struct pixrect *pr; { int plane_group; /* Get this window's choice of planes from kernel */ if (ioctl(windowfd, WINGETPLANEGROUP, &plane_group) == -1) { if (errno == ENOTTY) /* * For backwards compatibility reasons, * ignore fact that kernel not prepared for this call. * If we are running on an old kernel, then we * should not find ourselves running on a framebuffer * with multiple plane groups. This is because * there was no notion of plane groups in 3.0. * So, just use planes as full_planes. */ {} else (void)werror(-1, WINGETPLANEGROUP); plane_group = pr_get_plane_group(pr); } return (plane_group); } void win_set_plane_group(windowfd, new_plane_group) int windowfd; int new_plane_group; { if (ioctl(windowfd, WINSETPLANEGROUP, &new_plane_group) == -1) { if (errno == ENOTTY) /* * For backwards compatibility reasons, * ignore fact that kernel not prepared for this call. * If we are running on an old kernel, then we * should not find ourselves running on a framebuffer * with multiple plane groups. This is because * there was no notion of plane groups in 3.0. * * For forwards compatibility reasons, * the kernel knows that if it doesn't get this ioctl * that the plane group must be what the framebuffer * answered with to the FBIOTYPE call when suntools * was first started. */ {} else (void)werror(-1, WINSETPLANEGROUP); } } void win_get_plane_groups_available(windowfd, pr, available) int windowfd; struct pixrect *pr; struct win_plane_groups_available *available; { /* Get this screen's choice of plane groups from kernel */ if (ioctl(windowfd, WINGETAVAILPLANEGROUPS, available) == -1) { if (errno == ENOTTY) /* * For backwards compatibility reasons, * ignore fact that kernel not prepared for this call. * If we are running on an old kernel, then we * should not find ourselves running on a framebuffer * with multiple plane groups. */ {} else (void)werror(-1, WINGETAVAILPLANEGROUPS); available->plane_groups_available[pr_get_plane_group(pr)] = 1; } } void win_set_plane_groups_available(windowfd, available) int windowfd; struct win_plane_groups_available *available; { if (ioctl(windowfd, WINSETAVAILPLANEGROUPS, available) == -1) { if (errno == ENOTTY) /* * For backwards compatibility reasons, * ignore fact that kernel not prepared for this call. */ {} else (void)werror(-1, WINSETAVAILPLANEGROUPS); } } /* * Private routines: */ static void pw_initialize_plane_group(pw, plane_group, color, rdest) Pixwin *pw; int plane_group; int color; Rect *rdest; { struct rect rintersect; int planes_save, plane_group_save, full_planes = PIX_ALL_PLANES; struct pixrect *pr = pw->pw_clipdata->pwcd_prmulti; /* Remember original planes */ plane_group_save = pr_get_plane_group(pr); (void)pr_getattributes(pr, &planes_save); /* * Set plane group and planes. Set planes to enable writing offset, * effectively clears. */ pw_set_planes_directly(pw, plane_group, full_planes); /* Lock entire bounding rect of access */ (void)pw_lock(pw, rdest); /* Write background */ pw_begincliploop(pw, rdest, &rintersect); (void)pr_rop(pr, rintersect.r_left, rintersect.r_top, rintersect.r_width, rintersect.r_height, PIX_COLOR(color)|PIX_SRC|PIX_DONTCLIP, (Pixrect *)0, 0, 0); /* Terminate clipping loop */ pw_endcliploop(); /* Unlock */ (void)pw_unlock(pw); /* Reset planes & plane group */ pw_set_planes_directly(pw, plane_group_save, planes_save); } static void pw_initialize_invisible_pg(pw, invisible_pg, color, r, original_pg) Pixwin *pw; int invisible_pg; int color; Rect *r; int original_pg; { (void) win_set_plane_group(pw->pw_windowfd, invisible_pg); pw_initialize_plane_group(pw, invisible_pg, color, r); (void) win_set_plane_group(pw->pw_windowfd, original_pg); } /* Would make static if weren't worried about breaking someones program */ pw_setgrnd( pw, first, last, frred, frgreen, frblue, bkred, bkgreen, bkblue) struct pixwin *pw; int first, last; unsigned char frred, frgreen, frblue, bkred, bkgreen, bkblue; { unsigned char red[256], green[256], blue[256]; struct colormapseg cms; (void)pw_getcmsdata(pw, &cms, NO_PLANE_PTR); (void)pw_getcolormap( pw, 0, cms.cms_size, red, green, blue); red[first] = bkred; green[first] = bkgreen; blue[first] = bkblue; red[last] = frred; green[last] = frgreen; blue[last] = frblue; (void)pw_putcolormap( pw, 0, cms.cms_size, red, green, blue); } /* Referenced from pw_access.c */ pw_initcms(pw) register Pixwin *pw; { extern int pw_damaged(); u_char red[256], green[256], blue[256]; struct colormapseg cms; struct cms_map map; int new_planes; int original_plane_group, new_plane_group; int new_window; register int i; /* * Choose the initial colormap segment */ /* Set up default cms, but don't do anything to pw yet */ (void)pw_initdefaultcms(pw); /* Determine current window cms state */ (void)pw_getcmsdata(pw, &cms, NO_PLANE_PTR); /* The name indicates whether or not the cms has been set yet */ if (cms.cms_name[0] == '\0') { /* * The cms for this window hasn't been set yet. * So, initialize it to the default cms for this process. */ map.cm_red = red; map.cm_green = green; map.cm_blue = blue; cms.cms_size = 256; (void)pw_getdefaultcms(&cms, &map); /* Set the name in the pixwin */ (void)strncpy(pw->pw_cmsname, cms.cms_name, CMS_NAMESIZE); /* * Will prepare surface because first pixwin on window. * Is guaranteed to cover window because can't be region. */ new_window = 1; } else { /* Set the name in the pixwin (pw_getcolormap needs name set) */ (void)strncpy(pw->pw_cmsname, cms.cms_name, CMS_NAMESIZE); /* Initialize pixwin with existing cms */ (void)pw_getcolormap(pw, 0, cms.cms_size, red, green, blue); /* Wouldn't prepare surface because 1st pixwin did */ new_window = 0; } /* * Choose the initial plane group */ if (!pw_global_groups_available_set) { win_get_plane_groups_available(pw->pw_windowfd, pw->pw_pixrect, &pw_global_groups_available); pw_global_groups_available_set = 1; } /* Find out 'user' preference if not explicitly set by program */ if (!pw_plane_group_preference_set) pw_read_plane_group_preference(pw); /* Find out available planes from pixrect */ (void) pr_available_plane_groups(pw->pw_pixrect, PIX_MAX_PLANE_GROUPS, pw->pw_clipdata->pwcd_plane_groups_available); /* Restrict available planes */ for (i = 0; i < WIN_MAX_PLANE_GROUPS; i++) { if (pw->pw_clipdata->pwcd_plane_groups_available[i] && !pw_global_groups_available.plane_groups_available[i]) pw->pw_clipdata->pwcd_plane_groups_available[i] = 0; } /* Use existing plane group if already set */ if (!new_window) /* Use existing plane group */ original_plane_group = new_plane_group = win_get_plane_group(pw->pw_windowfd, pw->pw_pixrect); else { /* * The plane group for this window hasn't been set yet. * So, initialize it based on default cms name, user * preference and availability. */ new_plane_group = pw_choose_prefered_plane_group(pw, &original_plane_group); } /* * Set the initial plane group */ if (original_plane_group != new_plane_group) /* Tell kernel about this window's choice of plane group */ win_set_plane_group(pw->pw_windowfd, new_plane_group); /* Put plane group in pixrect (this may be redundant) */ pw_set_plane_group(pw, new_plane_group); /* * Set the pixrect planes attribute. We always choose the full * planes available to a given cms size. This is because the * planes attribute is associated with a pixrect, not the entire * window. */ /* Restrict planes */ if (pw->pw_clipdata->pwcd_flags & PWCD_COLOR24) new_planes = PIX_ALL_PLANES; else if (pw->pw_clipdata->pwcd_flags & PWCD_SET_CMAP_SIZE) { /* * set the mask to one less than the next power of 2 greater or * equal than the size of the cmap */ int mask; for (mask = 1; mask <= cms.cms_size; mask <<= 1); new_planes = mask - 1; } else new_planes = cms.cms_size - 1; /* * Put planes in pixrect for enabling of used planes. * This plane data will be propogated to rest of pixrect * when do pw_exposed (below). */ #ifdef planes_fully_implemented pr_putattributes(pw->pw_pixrect, &new_planes); #else (void)pw_full_putattributes(pw->pw_pixrect, &new_planes); #endif planes_fully_implemented /* * Set the initial colormap segment */ /* Set the cms (planes and colormap) */ (void)pw_putcolormap(pw, 0, cms.cms_size, red, green, blue); /* See if reinitializing the cms */ if (pw->pw_clipops->pwco_getclipping == pw_damaged) { /* Propagate plane related changes to all pixrects */ pw_set_planes_directly(pw, new_plane_group, new_planes); /* Assume being called from pw_preparesurface */ return; } /* Figure new clipping (initial getclipping op was nop) */ (void)pw_exposed(pw); /* * Prepare surface if first time opening pixwin on this window. * Previous attempts to call pw_preparesurface have been no-ops * because the clipping was null. RECT_NULL forces entire * visible area. */ if (new_window) (void)pw_preparesurface_full(pw, RECT_NULL, 1); } static void pw_read_plane_group_preference(pw) Pixwin *pw; { register char *en_str; char *getenv(); char *available_plane_groups = pw_global_groups_available.plane_groups_available; en_str=getenv("PW_PLANES"); if (en_str == NULL) goto Default; else if ((strcmp(en_str, "OVERLAY") == 0) || (strcmp(en_str, "BW") == 0)) pw_plane_group_preference = PIXPG_OVERLAY; else if ((strcmp(en_str, "COLOR") == 0) || (strcmp(en_str, "8BIT") == 0)) pw_plane_group_preference = PIXPG_8BIT_COLOR; else { Default: /* * Default based on available planes. Change order here * to affect entire systems color preference. * Current setup prefers the overlay plane. */ if (available_plane_groups[PIXPG_8BIT_COLOR]) pw_plane_group_preference = PIXPG_8BIT_COLOR; #ifndef PRE_IBIS else if (available_plane_groups[PIXPG_24BIT_COLOR]) pw_plane_group_preference = PIXPG_24BIT_COLOR; #endif else if (available_plane_groups[PIXPG_OVERLAY]) pw_plane_group_preference = PIXPG_OVERLAY; else if (pw->pw_pixrect->pr_depth == 1) pw_plane_group_preference = PIXPG_MONO; else pw_plane_group_preference = PIXPG_8BIT_COLOR; /* NOTE: ADD HERE WHEN HAVE NEW PLANE GROUP */ } /* NOTE: ADD HERE WHEN HAVE NEW PLANE GROUP */ pw_plane_group_preference_set = 1; } /* * The plane group for this window hasn't been set yet. * So, initialize it based on default cms name, user * preference and availability. */ static int pw_choose_prefered_plane_group(pw, original_plane_group) Pixwin *pw; int *original_plane_group; { char *plane_groups_available = pw->pw_clipdata->pwcd_plane_groups_available; int new_plane_group; *original_plane_group = pr_get_plane_group(pw->pw_pixrect); #ifdef notdef /* Use overlay plane for monochrome cms (if overlay is available) */ if ((strncmp(pw->pw_cmsname, CMS_MONOCHROME, CMS_NAMESIZE) == 0) && (plane_groups_available[PIXPG_OVERLAY])) new_plane_group = PIXPG_OVERLAY; /* * NOTE: ADD HERE WHEN HAVE NEW PLANE GROUP THAT HAS A STRONG * AFFINITY FOR A PARTICULAR CMS (like "monochrome"). */ /* See if want to make plane group the prefered group */ else #endif notdef #ifndef PRE_IBIS if (pw->pw_clipdata->pwcd_flags & PWCD_COLOR24) new_plane_group = PIXPG_24BIT_COLOR; else if (plane_groups_available[pw_plane_group_preference]) #else PRE_IBIS if (plane_groups_available[pw_plane_group_preference]) #endif else PRE_IBIS new_plane_group = pw_plane_group_preference; else new_plane_group = *original_plane_group; return (new_plane_group); } /* Would make static if weren't worried about breaking someones program */ pw_initdefaultcms(pw) struct pixwin *pw; { struct screen screen; register struct singlecolor *bkgnd; register struct singlecolor *frgnd; struct singlecolor *tmpgnd; if (pw_defaultcms.cms_size != 0) return; /* Initialize to monochrome cms. */ pw_defaultcms.cms_size = CMS_MONOCHROMESIZE; pw_defaultcms.cms_addr = 0; (void)strncpy(pw_defaultcms.cms_name, CMS_MONOCHROME, CMS_NAMESIZE); /* Adjust notion of foreground and background to match screen's. */ (void)win_screenget(pw->pw_clipdata->pwcd_windowfd, &screen); bkgnd = &screen.scr_background; frgnd = &screen.scr_foreground; if (screen.scr_flags & SCR_SWITCHBKGRDFRGRD) { tmpgnd = bkgnd; bkgnd = frgnd; frgnd = tmpgnd; } pw_defaultmap.cm_red[BLACK] = frgnd->red; pw_defaultmap.cm_green[BLACK] = frgnd->green; pw_defaultmap.cm_blue[BLACK] = frgnd->blue; pw_defaultmap.cm_red[WHITE] = bkgnd->red; pw_defaultmap.cm_green[WHITE] = bkgnd->green; pw_defaultmap.cm_blue[WHITE] = bkgnd->blue; } /* * Special fullscreen access routines: */ /* * Anyone calling these fullscreen_pw_* routines is assumed to have * done a fullscreen_init, is using the fullscreen pixwin during * this call, hasn't done any prepare surface under these bits, * and should be using a PIX_NOT(PIX_DST) operation. Also, pw_lock * should not have been called before using these operations. */ fullscreen_pw_vector(pw, x0, y0, x1, y1, op, cms_index) register struct pixwin *pw; int op; register int x0, y0, x1, y1; int cms_index; { int original_planes, original_plane_group; int current_plane_group; int left, top; int writestate; extern struct rect *pw_fullscreen_dbl_rect; /* if dbl buf active and intersects this line: do nothing */ if (pw_dbl_intersects_vector(pw, x0, y0, x1, y1)) return; /* if dbl buffering is active ensure to write on both planes */ if (pw_fullscreen_dbl_rect){ writestate = pr_dbl_get(pw->pw_pixrect, PR_DBL_WRITE); pr_dbl_set(pw->pw_pixrect, PR_DBL_WRITE, PR_DBL_BOTH, 0); } /* Draw vector in current plane group */ (void)pw_vector(pw, x0, y0, x1, y1, op, cms_index); /* Set up pw to draw in another plane group */ left = min(x0, x1); top = min(y0, y1); fullscreen_pw_start_plane_group_loop(pw, &original_planes, &original_plane_group, ¤t_plane_group); /* Draw in each applicable plane group */ while (fullscreen_pw_next_plane_group(pw, left, top, max(x0, x1)+1-left, max(y0, y1)+1-top, ¤t_plane_group, original_plane_group)) { /* Draw vector in alternate plane group */ (void)pw_vector(pw, x0, y0, x1, y1, op, cms_index); /* Undo what fullscreen_pw_next_plane_group did */ fullscreen_pw_finish_plane_group(pw, ¤t_plane_group, original_planes, original_plane_group); } if (pw_fullscreen_dbl_rect){ pr_dbl_set(pw->pw_pixrect, PR_DBL_WRITE, writestate, 0); } return; } fullscreen_pw_write(pw, xw, yw, width, height, op, pr, xr, yr) register Pixwin *pw; int op, xw, yw, width, height; struct pixrect *pr; int xr, yr; { int original_planes, original_plane_group; int current_plane_group; int writestate; extern struct rect *pw_fullscreen_dbl_rect; /* if dbl buf active and intersects this region: do nothing */ if (pw_dbl_intersects_region(pw, xw, yw, width, height)) return; /* if dbl buffering is active ensure to write on both planes */ if (pw_fullscreen_dbl_rect){ writestate = pr_dbl_get(pw->pw_pixrect, PR_DBL_WRITE); pr_dbl_set(pw->pw_pixrect, PR_DBL_WRITE, PR_DBL_BOTH, 0); } fullscreen_pw_start_plane_group_loop(pw, &original_planes, &original_plane_group, ¤t_plane_group); /* Draw in each applicable plane group */ while (fullscreen_pw_next_plane_group(pw, xw, yw, width, height, ¤t_plane_group, original_plane_group)) { /* Do rop in alternate plane group */ (void)pw_write(pw, xw, yw, width, height, op, pr, xr, yr); /* Undo what fullscreen_pw_next_plane_group did */ fullscreen_pw_finish_plane_group(pw, ¤t_plane_group, original_planes, original_plane_group); } if (pw_fullscreen_dbl_rect){ pr_dbl_set(pw->pw_pixrect, PR_DBL_WRITE, writestate, 0); } return; } #ifndef PRE_FLAMINGO static void fullscreen_pw_start_plane_group_loop(pw, original_planes, original_plane_group, current_plane_group) register Pixwin *pw; int *original_planes, *original_plane_group, *current_plane_group; { /* Remember current planes */ (void)pr_getattributes(pw->pw_pixrect, original_planes); /* Remember current plane group */ *original_plane_group = pw->pw_clipdata->pwcd_plane_group; /* Start with first plane group */ *current_plane_group = 1; } static int fullscreen_pw_next_plane_group(pw, left, top, width, height, current_plane_group, original_plane_group) register Pixwin *pw; int left, top, width, height; int *current_plane_group, original_plane_group; { char *available_plane_group = pw->pw_clipdata->pwcd_plane_groups_available; Rect rdest; /* Find next interesting plane group */ while (*current_plane_group < PIX_MAX_PLANE_GROUPS && (!available_plane_group[*current_plane_group] || *current_plane_group == PIXPG_OVERLAY_ENABLE || ((*current_plane_group == PIXPG_VIDEO_ENABLE) && !available_plane_group[PIXPG_VIDEO]) || *current_plane_group == PIXPG_VIDEO || *current_plane_group == PIXPG_WID|| *current_plane_group == PIXPG_CURSOR_ENABLE || *current_plane_group == PIXPG_CURSOR)) *current_plane_group += 1; if (*current_plane_group >= PIX_MAX_PLANE_GROUPS) return (0); if (*current_plane_group != original_plane_group) { /* Adjust operation's offset because didn't go thru macro */ left = PW_X_OFFSET(pw, left); top = PW_Y_OFFSET(pw, top); /* * Set new plane group temporarily so that cursor lifting is * done on the new plane group. */ pr_set_planes(pw->pw_pixrect, *current_plane_group, PIX_ALL_PLANES); /* * Lock pixwin so that clipping change doesn't blitz temporary * plane group changes. */ PW_SETUP(pw, rdest, Continue, left, top, width, height); Continue: /* * Set all pixrects to operate in all planes of given plane group. */ pw_set_planes_directly(pw, *current_plane_group, PIX_ALL_PLANES); } return (1); } #endif static void fullscreen_pw_finish_plane_group(pw, current_plane_group, original_planes, original_plane_group) register Pixwin *pw; int *current_plane_group, original_planes, original_plane_group; { if (*current_plane_group != original_plane_group) { /* Reset plane group accessing */ pw_set_planes_directly(pw, original_plane_group, original_planes); /* Unlock pixwin (was locked in fullscreen_pw_next_plane_group)*/ (void)pw_unlock(pw); /* * Set plane group back to original so that cursor lifting is * done on the original plane group (was set to new plane * group in fullscreen_pw_start_other_plane_group). */ pr_set_planes(pw->pw_pixrect, original_plane_group, original_planes); } *current_plane_group += 1; } static int fullscreen_pw_start_other_plane_group(pw, left, top, width, height, original_planes, original_plane_group) register Pixwin *pw; int left, top, width, height; int *original_planes, *original_plane_group; { char *available_plane_group = pw->pw_clipdata->pwcd_plane_groups_available; Rect rdest; int new_plane_group; /* Adjust operation's offset because didn't go thru macro */ left = PW_X_OFFSET(pw, left); top = PW_Y_OFFSET(pw, top); /* Remember current planes */ (void)pr_getattributes(pw->pw_pixrect, original_planes); /* Remember current plane group */ *original_plane_group = pw->pw_clipdata->pwcd_plane_group; /* * If we are in the 8 bit color plane group now and the overlay plane * is available then set things up to write in the overlay plane. */ #ifdef PRE_IBIS if ((*original_plane_group == PIXPG_8BIT_COLOR) && #else ndef PRE_IBIS if (((*original_plane_group == PIXPG_8BIT_COLOR) || (*original_plane_group == PIXPG_24BIT_COLOR)) && #endif else ndef PRE_IBIS (available_plane_group[PIXPG_OVERLAY])) new_plane_group = PIXPG_OVERLAY; /* * If we are in the overlay plane group now and the * 8 bit color plane group is available then set things * up to write in the 8 bit color plane group. */ #ifdef PRE_IBIS else if ((*original_plane_group == PIXPG_OVERLAY) && (available_plane_group[PIXPG_8BIT_COLOR])) new_plane_group = PIXPG_8BIT_COLOR; /* Else unknown plane group involved */ else #else ndef PRE_IBIS else if (*original_plane_group == PIXPG_OVERLAY) { if (available_plane_group [PIXPG_8BIT_COLOR]) new_plane_group = PIXPG_8BIT_COLOR; else if (available_plane_group [PIXPG_24BIT_COLOR]) new_plane_group = PIXPG_24BIT_COLOR; else return 0; } else /* Else unknown plane group involved */ #endif else ndef PRE_IBIS /* Return if no other plane groups to worry about */ return (0); /* * Set new plane group temporarily so that cursor lifting is * done on the new plane group. */ pr_set_planes(pw->pw_pixrect, new_plane_group, PIX_ALL_PLANES); /* * Lock pixwin so that clipping change doesn't blitz temporary * plane group changes. */ PW_SETUP(pw, rdest, Continue, left, top, width, height); Continue: /* * Set all pixrects to operate in all planes of given plane group. */ pw_set_planes_directly(pw, new_plane_group, PIX_ALL_PLANES); return (1); } static void fullscreen_pw_finish_other_plane_group(pw, original_planes, original_plane_group) register Pixwin *pw; int original_planes, original_plane_group; { /* Reset plane group accessing */ pw_set_planes_directly(pw, original_plane_group, original_planes); /* Unlock pixwin (was locked in fullscreen_pw_start_other_plane_group)*/ (void)pw_unlock(pw); /* * Set plane group back to original so that cursor lifting is * done on the original plane group (was set to new plane * group in fullscreen_pw_start_other_plane_group). */ pr_set_planes(pw->pw_pixrect, original_plane_group, original_planes); } void pw_set_planes_directly(pw, plane_group, planes) Pixwin *pw; int plane_group; int planes; { register struct pixwin_prlist *prl; register struct pixwin_clipdata *pwcd = pw->pw_clipdata; pw_set_planes_limited(pw, plane_group, planes); if (pwcd->pwcd_prmulti) { pr_set_planes(pwcd->pwcd_prmulti, plane_group, planes); pr_ioctl(pwcd->pwcd_prmulti, FBIOSWINFD, &pw->pw_clipdata->pwcd_windowfd); } if (pwcd->pwcd_prsingle) { pr_set_planes(pwcd->pwcd_prsingle, plane_group, planes); /*####ACG pr_ioctl(pwcd->pwcd_prsingle, FBIOSWINFD, &pw->pw_clipdata->pwcd_windowfd); ####*/ } for (prl = pwcd->pwcd_prl;prl;prl = prl->prl_next) { pr_set_planes(prl->prl_pixrect, plane_group, planes); pr_ioctl(prl->prl_pixrect, FBIOSWINFD, &pw->pw_clipdata->pwcd_windowfd); } } void fullscreen_pw_copy(pw, xw, yw, width, height, op, pw_src, xr, yr) Pixwin *pw; register int op, xw, yw, width, height; Pixwin *pw_src; int xr, yr; { int i, original_plane_group; int original_planes; register struct pixrect *pr; unsigned char elim_groups[PIX_MAX_PLANE_GROUPS]; /* only screen to screen copy */ if (pw != pw_src) return; /* save the original state */ pr = pw->pw_pixrect; original_plane_group = pr_get_plane_group(pr); (void) pr_getattributes(pr, &original_planes); /* * Loop through all plane groups. * * Note: the older code (correctly) copied the active plane group first to * make it "appear" faster and avoided "ghost" images by making sure of * the order in which enable planes where copied. Unfortunately, the * advent of a 24 bit plane group with 12-bit double buffering really * confuses matters. This is further muddied by the fact that if ANY * plane group double buffers, the PWCD_DBL_AVAIL flag is set. */ /* * Some planes are inappropriate for fullscreen operations. * Remove them from the list to be copied. */ (void) pr_ioctl(pr, FBIOSWINFD, &pw->pw_clipdata->pwcd_windowfd); (void) bzero(elim_groups, PIX_MAX_PLANE_GROUPS); (void) pr_ioctl(pr, FBIO_FULLSCREEN_ELIMINATION_GROUPS, elim_groups); /* * Do video enable memory first since on sbus cgeight board this is in same * memory as the 24-bit color. */ if (pw->pw_clipdata->pwcd_plane_groups_available[PIXPG_VIDEO_ENABLE] && !elim_groups[PIXPG_VIDEO_ENABLE]) { pr_set_planes(pr, PIXPG_VIDEO_ENABLE, PIX_ALL_PLANES); (void) pr_rop(pr, xw, yw, width, height, op, pr, xr, yr); elim_groups[PIXPG_VIDEO_ENABLE] = 0;/* So we don't copy it twice!!! */ } for (i = 1; i < PIX_MAX_PLANE_GROUPS; i++) { if (pw->pw_clipdata->pwcd_plane_groups_available[i] && !elim_groups[i]) { pr_set_planes(pr, i, PIX_ALL_PLANES); /* Double buffer case. cg{3,5} work. cg9 questionable */ if (pw->pw_clipdata->pwcd_flags & PWCD_DBL_AVAIL && pr_dbl_get(pr, PR_DBL_AVAIL_PG) == PR_DBL_EXISTS) { register int read, write; read = pr_dbl_get(pr, PR_DBL_READ); write = pr_dbl_get(pr, PR_DBL_WRITE); pr_dbl_set(pr, PR_DBL_READ, PR_DBL_A, PR_DBL_WRITE, PR_DBL_A,0); (void) pr_rop(pr, xw, yw, width, height, op, pr, xr, yr); pr_dbl_set(pr, PR_DBL_READ, PR_DBL_B, PR_DBL_WRITE, PR_DBL_B,0); (void) pr_rop(pr, xw, yw, width, height, op, pr, xr, yr); pr_dbl_set(pr, PR_DBL_READ, read, PR_DBL_WRITE, write, 0); } else { (void) pr_rop(pr, xw, yw, width, height, op, pr, xr, yr); } } } /* Restore state */ pr_set_planes(pr, original_plane_group, original_planes); return; } Pw_pixel_cache * pw_save_pixels(pw, r) register Pixwin *pw; register Rect *r; { register int pg; register struct pixrect *pr = pw->pw_pixrect; struct pixrect *mpr; Pw_pixel_cache *pc; caddr_t calloc(); int original_plane_group, original_planes; register struct pixwin_clipdata *pwcd = pw->pw_clipdata; /* Allocate pixel cache */ pc = (Pw_pixel_cache *)calloc(sizeof(Pw_pixel_cache), 1); if (pc == PW_PIXEL_CACHE_NULL) goto NoMem; pc->r = *r; /* * ugly but necessary to turn of 8-bit emulation for fullscreen op. * this is a no-op for non-24-bit frame buffers. */ (void) pr_ioctl(pw->pw_pixrect, FBIOSAVWINFD, 0); /* Remember original plane state */ original_plane_group = pr_get_plane_group(pr); (void)pr_getattributes(pr, &original_planes); /* Cycle through available plane groups */ for (pg = 0; pg < PIX_MAX_PLANE_GROUPS; pg++) { if ((pwcd->pwcd_plane_groups_available[pg]) && (pg != PIXPG_CURSOR)&& (pg != PIXPG_CURSOR_ENABLE)) { /* Set plane group to pg */ pw_set_planes_limited(pw, pg, PIX_ALL_PLANES); /* Allocate a mpr */ mpr = mem_create(r->r_width, r->r_height, pr->pr_depth); if (mpr == (struct pixrect *)0) goto NoMem; /* * Save pixels. * * Subvert the pixwin interface, * because pw_read requires a * PIX_DONTCLIP|PIX_SRC to not clip to * the src (the window) but the PIX_DONTCLIP * flags makes the call unsafe if try to read * from off the screen. */ (void)pw_lock(pw, r); (void)pr_rop(mpr, 0, 0, r->r_width, r->r_height, PIX_SRC, pr, r->r_left + pwcd->pwcd_screen_x, r->r_top + pwcd->pwcd_screen_y); (void)pw_unlock(pw); /* Note in data structure */ pc->plane_group[pg] = mpr; } } /* Set plane state to original */ pw_set_planes_limited(pw, original_plane_group, original_planes); pr_ioctl(pw->pw_pixrect, FBIORESWINFD, 0); return (pc); NoMem: (void)fprintf(stderr, "Couldn't allocate memory in pw_save_pixels\n"); pw_restore_pixels(pw, pc); return (PW_PIXEL_CACHE_NULL); } void pw_restore_pixels(pw, pc) register Pixwin *pw; Pw_pixel_cache *pc; { register int pg; register struct pixrect *pr = pw->pw_pixrect; struct pixrect *mpr; int original_plane_group, original_planes; register Rect *r = &pc->r; unsigned char elim_groups[PIX_MAX_PLANE_GROUPS]; if (pc == PW_PIXEL_CACHE_NULL) return; /* * ugly but necessary to turn of 8-bit emulation for fullscreen op. * this is a no-op for non-24-bit frame buffers. */ pr_ioctl(pw->pw_pixrect, FBIOSAVWINFD, 0); /* * Do video enable plane first, since pip video will "bleed through" * unless it is set properly */ if (mpr = pc->plane_group[PIXPG_VIDEO_ENABLE]) { pg = PIXPG_VIDEO_ENABLE; /* Remember original plane state */ original_plane_group = pr_get_plane_group(pr); (void) pr_getattributes(pr, &original_planes); /* Set plane group to pg */ pw_set_planes_limited(pw, pg, PIX_ALL_PLANES); /* Restore pixels */ (void) pw_lock(pw, r); (void) pr_rop(pr, r->r_left + pw->pw_clipdata->pwcd_screen_x, r->r_top + pw->pw_clipdata->pwcd_screen_y, r->r_width, r->r_height, PIX_SRC, mpr, 0, 0); (void) pw_unlock(pw); /* Set plane state to original */ pw_set_planes_limited(pw, original_plane_group, original_planes); /* Free the mpr */ mem_destroy(mpr); pc->plane_group[pg] = (struct pixrect *)0; } /* Cycle through available plane groups */ for (pg = 0; pg < PIX_MAX_PLANE_GROUPS; pg++) { /* * Only restore what was saved. */ if ((pg == PIXPG_CURSOR) || (pg == PIXPG_CURSOR_ENABLE)) continue; mpr = pc->plane_group[pg]; if (mpr != (struct pixrect *)0) { /* Remember original plane state */ original_plane_group = pr_get_plane_group(pr); (void)pr_getattributes(pr, &original_planes); /* Set plane group to pg */ pw_set_planes_limited(pw, pg, PIX_ALL_PLANES); /* Restore pixels */ (void)pw_lock(pw, r); (void)pr_rop(pr, r->r_left + pw->pw_clipdata->pwcd_screen_x, r->r_top + pw->pw_clipdata->pwcd_screen_y, r->r_width, r->r_height, PIX_SRC, mpr, 0, 0); (void)pw_unlock(pw); /* Set plane state to original */ pw_set_planes_limited(pw, original_plane_group, original_planes); /* Free the mpr */ mem_destroy(mpr); } } /* Free pixel cache */ free((caddr_t)pc); pr_ioctl(pw->pw_pixrect, FBIORESWINFD, 0); return; } static void pw_set_planes_limited(pw, plane_group, planes) Pixwin *pw; int plane_group; int planes; { pw->pw_clipdata->pwcd_plane_group = plane_group; pr_set_planes(pw->pw_pixrect, plane_group, planes); } static void pw_set_plane_group(pw, plane_group) Pixwin *pw; int plane_group; { pw->pw_clipdata->pwcd_plane_group = plane_group; pr_set_plane_group(pw->pw_pixrect, plane_group); } #ifndef planes_fully_implemented pw_full_putattributes(pr, planes) struct pixrect *pr; int *planes; { pr_set_planes(pr, pr_get_plane_group(pr), *planes); } #endif planes_fully_implemented #ifdef using_pixwin_attr_interface #define PIXWIN_ATTR(type, ordinal) ATTR(ATTR_PKG_PIXWIN, type, ordinal) typedef enum { /* boolean attributes */ PIXWIN_IS_COLOR_AVAILABLE = PIXWIN_ATTR(ATTR_BOOLEAN, 1), PIXWIN_IS_FAST_MONO_AVAILABLE = PIXWIN_ATTR(ATTR_BOOLEAN, 2), /* integer attributes */ PIXWIN_DEPTH_RETAIN = PIXWIN_ATTR(ATTR_INT, 20), PIXWIN_DEPTH_AVAILABLE = PIXWIN_ATTR(ATTR_INT, 21), PIXWIN_DEPTH_UNDER = PIXWIN_ATTR(ATTR_INT, 22), } Pixwin_attribute; extern caddr_t pixwin_get(); extern int pixwin_set(); /* pixwin_get returns the current value of which_attr. */ caddr_t pixwin_get(pixwin, which_attr) register struct pixwin *pixwin; Pixwin_attribute which_attr; { switch (which_attr) { case PIXWIN_IS_COLOR_AVAILABLE: return (caddr_t) ((int) pixwin_get(pixwin, PIXWIN_DEPTH_AVAILABLE) > 1); case PIXWIN_DEPTH_RETAIN: { struct colormapseg cms; (void)pw_getcmsdata(pixwin, &cms, NO_PLANE_PTR); return (caddr_t) ((cms.cms_size == 2)? 1: pixwin->pw_pixrect->pr_depth); } case PIXWIN_DEPTH_AVAILABLE: { int depth; char *plane_groups_available = pixwin->pw_clipdata->pwcd_plane_groups_available; if (plane_groups_available[PIXPG_8BIT_COLOR]) depth = 8; else depth = 1; /* NOTE: ADD HERE WHEN INVENTING NEW PLANE GROUP */ return (caddr_t) depth; } case PIXWIN_DEPTH_UNDER: return (caddr_t) pixwin->pw_pixrect->pr_depth; default: return (caddr_t) 0; } } /* pixwin_get */ int pixwin_set(pixwin, arg1) struct pixwin *pixwin; caddr_t arg1; { caddr_t avlist[ATTR_STANDARD_SIZE]; int pixwin_set_attr(); attr_make(avlist, ATTR_STANDARD_SIZE, &arg1); return pixwin_set_attr(pixwin, avlist); } /* pixwin_set_attr sets the attributes mentioned in avlist. */ static int pixwin_set_attr(pixwin, avlist) register struct pixwin *pixwin; register Attr_avlist avlist; { register Pixwin_attribute which_attr; while (which_attr = (Pixwin_attribute) *avlist++) { switch (which_attr) { case PIXWIN_IS_COLOR_AVAILABLE: case PIXWIN_DEPTH_RETAIN: case PIXWIN_DEPTH_AVAILABLE: case PIXWIN_DEPTH_UNDER: default: /* Here we should complain about something */ return 1; } } return 0; } /* pixwin_set */ #endif using_pixwin_attr_interface