/** * Private function for creating an XMesaBuffer which corresponds to an * X window or pixmap. * \param v the window's XMesaVisual * \param w the window we're wrapping * \return new XMesaBuffer or NULL if error */ PUBLIC XMesaBuffer XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) { XWindowAttributes attr; XMesaBuffer b; XMesaColormap cmap; int depth; assert(v); assert(w); /* Check that window depth matches visual depth */ XGetWindowAttributes( v->display, w, &attr ); depth = attr.depth; if (GET_VISUAL_DEPTH(v) != depth) { _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", GET_VISUAL_DEPTH(v), depth); return NULL; } /* Find colormap */ if (attr.colormap) { cmap = attr.colormap; } else { _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); /* this is weird, a window w/out a colormap!? */ /* OK, let's just allocate a new one and hope for the best */ cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); } b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap); if (!b) return NULL; if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) { xmesa_free_buffer(b); return NULL; } return b; }
/** * Setup an off-screen pixmap or Ximage to use as the back buffer. * Input: b - the X/Mesa buffer */ static void alloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) { if (b->db_mode == BACK_XIMAGE) { /* Deallocate the old backxrb->ximage, if any */ if (b->backxrb->ximage) { #if defined(USE_XSHM) if (b->shm) { XShmDetach(b->xm_visual->display, &b->shminfo); XDestroyImage(b->backxrb->ximage); shmdt(b->shminfo.shmaddr); } else #endif XMesaDestroyImage(b->backxrb->ximage); b->backxrb->ximage = NULL; } if (width == 0 || height == 0) return; /* Allocate new back buffer */ if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) { /* Allocate a regular XImage for the back buffer. */ b->backxrb->ximage = XCreateImage(b->xm_visual->display, b->xm_visual->visinfo->visual, GET_VISUAL_DEPTH(b->xm_visual), ZPixmap, 0, /* format, offset */ NULL, width, height, 8, 0); /* pad, bytes_per_line */ if (!b->backxrb->ximage) { _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n"); return; } b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height * b->backxrb->ximage->bytes_per_line); if (!b->backxrb->ximage->data) { _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n"); XMesaDestroyImage(b->backxrb->ximage); b->backxrb->ximage = NULL; } } b->backxrb->pixmap = None; } else if (b->db_mode == BACK_PIXMAP) { /* Free the old back pixmap */ if (b->backxrb->pixmap) { XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap); b->backxrb->pixmap = 0; } if (width > 0 && height > 0) { /* Allocate new back pixmap */ b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display, b->frontxrb->drawable, width, height, GET_VISUAL_DEPTH(b->xm_visual)); } b->backxrb->ximage = NULL; b->backxrb->drawable = b->backxrb->pixmap; } }
/* * Create a new X/Mesa visual. * Input: display - X11 display * visinfo - an XVisualInfo pointer * rgb_flag - GL_TRUE = RGB mode, * GL_FALSE = color index mode * alpha_flag - alpha buffer requested? * db_flag - GL_TRUE = double-buffered, * GL_FALSE = single buffered * stereo_flag - stereo visual? * ximage_flag - GL_TRUE = use an XImage for back buffer, * GL_FALSE = use an off-screen pixmap for back buffer * depth_size - requested bits/depth values, or zero * stencil_size - requested bits/stencil values, or zero * accum_red_size - requested bits/red accum values, or zero * accum_green_size - requested bits/green accum values, or zero * accum_blue_size - requested bits/blue accum values, or zero * accum_alpha_size - requested bits/alpha accum values, or zero * num_samples - number of samples/pixel if multisampling, or zero * level - visual level, usually 0 * visualCaveat - ala the GLX extension, usually GLX_NONE * Return; a new XMesaVisual or 0 if error. */ PUBLIC XMesaVisual XMesaCreateVisual( XMesaDisplay *display, XMesaVisualInfo visinfo, GLboolean rgb_flag, GLboolean alpha_flag, GLboolean db_flag, GLboolean stereo_flag, GLboolean ximage_flag, GLint depth_size, GLint stencil_size, GLint accum_red_size, GLint accum_green_size, GLint accum_blue_size, GLint accum_alpha_size, GLint num_samples, GLint level, GLint visualCaveat ) { char *gamma; XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. * In your debugger, set a breakpoint on _XError to stop when an * X protocol error is generated. */ XSynchronize( display, 1 ); } /* Color-index rendering not supported. */ if (!rgb_flag) return NULL; v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); if (!v) { return NULL; } v->display = display; /* Save a copy of the XVisualInfo struct because the user may Xfree() * the struct but we may need some of the information contained in it * at a later time. */ v->visinfo = (XVisualInfo *) malloc(sizeof(*visinfo)); if(!v->visinfo) { free(v); return NULL; } memcpy(v->visinfo, visinfo, sizeof(*visinfo)); /* check for MESA_GAMMA environment variable */ gamma = _mesa_getenv("MESA_GAMMA"); if (gamma) { v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); if (v->RedGamma<=0.0) v->RedGamma = 1.0; if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; } else { v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; } v->ximage_flag = ximage_flag; v->mesa_visual.redMask = visinfo->red_mask; v->mesa_visual.greenMask = visinfo->green_mask; v->mesa_visual.blueMask = visinfo->blue_mask; v->visualID = visinfo->visualid; v->screen = visinfo->screen; #if !(defined(__cplusplus) || defined(c_plusplus)) v->visualType = xmesa_convert_from_x_visual_type(visinfo->class); #else v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); #endif v->mesa_visual.visualRating = visualCaveat; if (alpha_flag) v->mesa_visual.alphaBits = 8; (void) initialize_visual_and_buffer( v, NULL, 0, 0 ); { const int xclass = v->visualType; if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { red_bits = _mesa_bitcount(GET_REDMASK(v)); green_bits = _mesa_bitcount(GET_GREENMASK(v)); blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); } else { /* this is an approximation */ int depth; depth = GET_VISUAL_DEPTH(v); red_bits = depth / 3; depth -= red_bits; green_bits = depth / 2; depth -= green_bits; blue_bits = depth; alpha_bits = 0; assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); } alpha_bits = v->mesa_visual.alphaBits; } if (!_mesa_initialize_visual(&v->mesa_visual, db_flag, stereo_flag, red_bits, green_bits, blue_bits, alpha_bits, depth_size, stencil_size, accum_red_size, accum_green_size, accum_blue_size, accum_alpha_size, 0)) { FREE(v); return NULL; } /* XXX minor hack */ v->mesa_visual.level = level; return v; }
/** * When a context is bound for the first time, we can finally finish * initializing the context's visual and buffer information. * \param v the XMesaVisual to initialize * \param b the XMesaBuffer to initialize (may be NULL) * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode * \param window the window/pixmap we're rendering into * \param cmap the colormap associated with the window/pixmap * \return GL_TRUE=success, GL_FALSE=failure */ static GLboolean initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, XMesaDrawable window, XMesaColormap cmap) { const int xclass = v->visualType; ASSERT(!b || b->xm_visual == v); /* Save true bits/pixel */ v->BitsPerPixel = bits_per_pixel(v); assert(v->BitsPerPixel > 0); /* RGB WINDOW: * We support RGB rendering into almost any kind of visual. */ if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { setup_truecolor( v, b, cmap ); } else { _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); return GL_FALSE; } v->mesa_visual.indexBits = 0; if (_mesa_getenv("MESA_NO_DITHER")) { v->dithered_pf = v->undithered_pf; } /* * If MESA_INFO env var is set print out some debugging info * which can help Brian figure out what's going on when a user * reports bugs. */ if (_mesa_getenv("MESA_INFO")) { printf("X/Mesa visual = %p\n", (void *) v); printf("X/Mesa dithered pf = %u\n", v->dithered_pf); printf("X/Mesa undithered pf = %u\n", v->undithered_pf); printf("X/Mesa level = %d\n", v->mesa_visual.level); printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); } if (b && window) { /* Do window-specific initializations */ /* these should have been set in create_xmesa_buffer */ ASSERT(b->frontxrb->drawable == window); ASSERT(b->frontxrb->pixmap == (XMesaPixmap) window); /* Setup for single/double buffering */ if (v->mesa_visual.doubleBufferMode) { /* Double buffered */ b->shm = check_for_xshm( v->display ); } /* X11 graphics contexts */ b->gc = XCreateGC( v->display, window, 0, NULL ); XMesaSetFunction( v->display, b->gc, GXcopy ); /* cleargc - for glClear() */ b->cleargc = XCreateGC( v->display, window, 0, NULL ); XMesaSetFunction( v->display, b->cleargc, GXcopy ); /* * Don't generate Graphics Expose/NoExpose events in swapbuffers(). * Patch contributed by Michael Pichler May 15, 1995. */ { XGCValues gcvalues; gcvalues.graphics_exposures = False; b->swapgc = XCreateGC(v->display, window, GCGraphicsExposures, &gcvalues); } XMesaSetFunction( v->display, b->swapgc, GXcopy ); } return GL_TRUE; }
/** * Setup RGB rendering for a window with a True/DirectColor visual. */ static void setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) { unsigned long rmask, gmask, bmask; (void) buffer; (void) cmap; /* Compute red multiplier (mask) and bit shift */ v->rshift = 0; rmask = GET_REDMASK(v); while ((rmask & 1)==0) { v->rshift++; rmask = rmask >> 1; } /* Compute green multiplier (mask) and bit shift */ v->gshift = 0; gmask = GET_GREENMASK(v); while ((gmask & 1)==0) { v->gshift++; gmask = gmask >> 1; } /* Compute blue multiplier (mask) and bit shift */ v->bshift = 0; bmask = GET_BLUEMASK(v); while ((bmask & 1)==0) { v->bshift++; bmask = bmask >> 1; } /* * Compute component-to-pixel lookup tables and dithering kernel */ { static GLubyte kernel[16] = { 0*16, 8*16, 2*16, 10*16, 12*16, 4*16, 14*16, 6*16, 3*16, 11*16, 1*16, 9*16, 15*16, 7*16, 13*16, 5*16, }; GLint rBits = _mesa_bitcount(rmask); GLint gBits = _mesa_bitcount(gmask); GLint bBits = _mesa_bitcount(bmask); GLint maxBits; GLuint i; /* convert pixel components in [0,_mask] to RGB values in [0,255] */ for (i=0; i<=rmask; i++) v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); for (i=0; i<=gmask; i++) v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); for (i=0; i<=bmask; i++) v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); /* convert RGB values from [0,255] to pixel components */ for (i=0;i<256;i++) { GLint r = gamma_adjust(v->RedGamma, i, 255); GLint g = gamma_adjust(v->GreenGamma, i, 255); GLint b = gamma_adjust(v->BlueGamma, i, 255); v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; } /* overflow protection */ for (i=256;i<512;i++) { v->RtoPixel[i] = v->RtoPixel[255]; v->GtoPixel[i] = v->GtoPixel[255]; v->BtoPixel[i] = v->BtoPixel[255]; } /* setup dithering kernel */ maxBits = rBits; if (gBits > maxBits) maxBits = gBits; if (bBits > maxBits) maxBits = bBits; for (i=0;i<16;i++) { v->Kernel[i] = kernel[i] >> maxBits; } v->undithered_pf = PF_Truecolor; v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; } /* * Now check for TrueColor visuals which we can optimize. */ if ( GET_REDMASK(v) ==0x0000ff && GET_GREENMASK(v)==0x00ff00 && GET_BLUEMASK(v) ==0xff0000 && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==32 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { /* common 32 bpp config used on SGI, Sun */ v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ } else if (GET_REDMASK(v) == 0xff0000 && GET_GREENMASK(v)== 0x00ff00 && GET_BLUEMASK(v) == 0x0000ff && CHECK_BYTE_ORDER(v) && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ if (v->BitsPerPixel==32) { /* if 32 bpp, and visual indicates 8 bpp alpha channel */ if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ else v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ } else if (v->BitsPerPixel == 24) { v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ } } else if (GET_REDMASK(v) ==0xf800 && GET_GREENMASK(v)==0x07e0 && GET_BLUEMASK(v) ==0x001f && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==16 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { /* 5-6-5 RGB */ v->undithered_pf = PF_5R6G5B; v->dithered_pf = PF_Dither_5R6G5B; } }
static swrast_tri_func get_triangle_func( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); XMesaContext xmesa = XMESA_CONTEXT(ctx); int depth = GET_VISUAL_DEPTH(xmesa->xm_visual); GET_XRB(xrb); #ifdef DEBUG triFuncName = NULL; #endif if ((ctx->DrawBuffer->_ColorDrawBufferMask[0] & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0) return (swrast_tri_func) NULL; if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_tri_func) NULL; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) return (swrast_tri_func) NULL; if (xrb->ximage) { if ( ctx->Light.ShadeModel==GL_SMOOTH && swrast->_RasterMask==DEPTH_BIT && ctx->Depth.Func==GL_LESS && ctx->Depth.Mask==GL_TRUE && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS && ctx->Polygon.StippleFlag==GL_FALSE) { switch (xmesa->pixelformat) { case PF_Truecolor: USE(smooth_TRUECOLOR_z_triangle); case PF_8A8B8G8R: USE(smooth_8A8B8G8R_z_triangle); case PF_8A8R8G8B: USE(smooth_8A8R8G8B_z_triangle); case PF_8R8G8B: USE(smooth_8R8G8B_z_triangle); case PF_8R8G8B24: USE(smooth_8R8G8B24_z_triangle); case PF_Dither_True: USE(smooth_TRUEDITHER_z_triangle); case PF_5R6G5B: USE(smooth_5R6G5B_z_triangle); case PF_Dither_5R6G5B: USE(smooth_DITHER_5R6G5B_z_triangle); case PF_HPCR: USE(smooth_HPCR_z_triangle); case PF_Dither: if (depth == 8) USE(smooth_DITHER8_z_triangle); else USE(smooth_DITHER_z_triangle); case PF_Lookup: if (depth == 8) USE(smooth_LOOKUP8_z_triangle); else return (swrast_tri_func) NULL; default: return (swrast_tri_func) NULL; } } if ( ctx->Light.ShadeModel==GL_FLAT && swrast->_RasterMask==DEPTH_BIT && ctx->Depth.Func==GL_LESS && ctx->Depth.Mask==GL_TRUE && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS && ctx->Polygon.StippleFlag==GL_FALSE) { switch (xmesa->pixelformat) { case PF_Truecolor: USE(flat_TRUECOLOR_z_triangle); case PF_8A8B8G8R: USE(flat_8A8B8G8R_z_triangle); case PF_8A8R8G8B: USE(flat_8A8R8G8B_z_triangle); case PF_8R8G8B: USE(flat_8R8G8B_z_triangle); case PF_8R8G8B24: USE(flat_8R8G8B24_z_triangle); case PF_Dither_True: USE(flat_TRUEDITHER_z_triangle); case PF_5R6G5B: USE(flat_5R6G5B_z_triangle); case PF_Dither_5R6G5B: USE(flat_DITHER_5R6G5B_z_triangle); case PF_HPCR: USE(flat_HPCR_z_triangle); case PF_Dither: if (depth == 8) USE(flat_DITHER8_z_triangle); else USE(flat_DITHER_z_triangle); case PF_Lookup: if (depth == 8) USE(flat_LOOKUP8_z_triangle); else return (swrast_tri_func) NULL; default: return (swrast_tri_func) NULL; } } if ( swrast->_RasterMask==0 /* no depth test */ && ctx->Light.ShadeModel==GL_SMOOTH && ctx->Polygon.StippleFlag==GL_FALSE) { switch (xmesa->pixelformat) { case PF_Truecolor: USE(smooth_TRUECOLOR_triangle); case PF_8A8B8G8R: USE(smooth_8A8B8G8R_triangle); case PF_8A8R8G8B: USE(smooth_8A8R8G8B_triangle); case PF_8R8G8B: USE(smooth_8R8G8B_triangle); case PF_8R8G8B24: USE(smooth_8R8G8B24_triangle); case PF_Dither_True: USE(smooth_TRUEDITHER_triangle); case PF_5R6G5B: USE(smooth_5R6G5B_triangle); case PF_Dither_5R6G5B: USE(smooth_DITHER_5R6G5B_triangle); case PF_HPCR: USE(smooth_HPCR_triangle); case PF_Dither: if (depth == 8) USE(smooth_DITHER8_triangle); else USE(smooth_DITHER_triangle); case PF_Lookup: if (depth == 8) USE(smooth_LOOKUP8_triangle); else return (swrast_tri_func) NULL; default: return (swrast_tri_func) NULL; } } if ( swrast->_RasterMask==0 /* no depth test */ && ctx->Light.ShadeModel==GL_FLAT && ctx->Polygon.StippleFlag==GL_FALSE) { switch (xmesa->pixelformat) { case PF_Truecolor: USE(flat_TRUECOLOR_triangle); case PF_Dither_True: USE(flat_TRUEDITHER_triangle); case PF_8A8B8G8R: USE(flat_8A8B8G8R_triangle); case PF_8A8R8G8B: USE(flat_8A8R8G8B_triangle); case PF_8R8G8B: USE(flat_8R8G8B_triangle); case PF_8R8G8B24: USE(flat_8R8G8B24_triangle); case PF_5R6G5B: USE(flat_5R6G5B_triangle); case PF_Dither_5R6G5B: USE(flat_DITHER_5R6G5B_triangle); case PF_HPCR: USE(flat_HPCR_triangle); case PF_Dither: if (depth == 8) USE(flat_DITHER8_triangle); else USE(flat_DITHER_triangle); case PF_Lookup: if (depth == 8) USE(flat_LOOKUP8_triangle); else return (swrast_tri_func) NULL; default: return (swrast_tri_func) NULL; } } return (swrast_tri_func) NULL; } else { /* draw to pixmap */ return (swrast_tri_func) NULL; } }