📄 xm_api.c
字号:
/* * Find an XMesaBuffer by matching X display and colormap but NOT matching * the notThis buffer. */static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis){ XMesaBuffer b; for (b=XMesaBufferList; b; b=b->Next) { if (b->display==dpy && b->cmap==cmap && b!=notThis) { return b; } } return NULL;}/* * Free an XMesaBuffer, remove from linked list, perhaps free X colormap * entries. */static void free_xmesa_buffer(int client, XMesaBuffer buffer){ XMesaBuffer prev = NULL, b; (void) client; for (b=XMesaBufferList; b; b=b->Next) { if (b==buffer) { /* unlink bufer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; /* Check to free X colors */ if (buffer->num_alloced>0) { /* If no other buffer uses this X colormap then free the colors. */ if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {#ifdef XFree86Server (void)FreeColors(buffer->cmap, client, buffer->num_alloced, buffer->alloced_colors, 0);#else XFreeColors(buffer->display, buffer->cmap, buffer->alloced_colors, buffer->num_alloced, 0);#endif } } _mesa_free_framebuffer_data(&buffer->mesa_buffer); _mesa_free(buffer); return; } /* continue search */ prev = b; } /* buffer not found in XMesaBufferList */ _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");}/* Copy X color table stuff from one XMesaBuffer to another. */static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src){ MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g)); MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b)); dst->num_alloced = src->num_alloced; MEMCPY(dst->alloced_colors, src->alloced_colors, sizeof(src->alloced_colors));}/**********************************************************************//***** Misc Private Functions *****//**********************************************************************//** * Allocate a shared memory XImage back buffer for the given XMesaBuffer. * Return: GL_TRUE if success, GL_FALSE if error */#ifndef XFree86Serverstatic GLbooleanalloc_shm_back_buffer(XMesaBuffer b, GLuint width, GLuint height){#ifdef USE_XSHM /* * We have to do a _lot_ of error checking here to be sure we can * really use the XSHM extension. It seems different servers trigger * errors at different points if the extension won't work. Therefore * we have to be very careful... */ GC gc; int (*old_handler)( XMesaDisplay *, XErrorEvent * ); if (width == 0 || height == 0) { /* this will be true the first time we're called on 'b' */ return GL_FALSE; } b->backxrb->ximage = XShmCreateImage(b->xm_visual->display, b->xm_visual->visinfo->visual, b->xm_visual->visinfo->depth, ZPixmap, NULL, &b->shminfo, width, height); if (b->backxrb->ximage == NULL) { _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.shmid = shmget( IPC_PRIVATE, b->backxrb->ximage->bytes_per_line * b->backxrb->ximage->height, IPC_CREAT|0777 ); if (b->shminfo.shmid < 0) { _mesa_warning(NULL, "shmget failed while allocating back buffer.\n"); XDestroyImage( b->backxrb->ximage ); b->backxrb->ximage = NULL; _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.shmaddr = b->backxrb->ximage->data = (char*)shmat( b->shminfo.shmid, 0, 0 ); if (b->shminfo.shmaddr == (char *) -1) { _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n"); XDestroyImage( b->backxrb->ximage ); shmctl( b->shminfo.shmid, IPC_RMID, 0 ); b->backxrb->ximage = NULL; _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n"); b->shm = 0; return GL_FALSE; } b->shminfo.readOnly = False; mesaXErrorFlag = 0; old_handler = XSetErrorHandler( mesaHandleXError ); /* This may trigger the X protocol error we're ready to catch: */ XShmAttach( b->xm_visual->display, &b->shminfo ); XSync( b->xm_visual->display, False ); if (mesaXErrorFlag) { /* we are on a remote display, this error is normal, don't print it */ XFlush( b->xm_visual->display ); mesaXErrorFlag = 0; XDestroyImage( b->backxrb->ximage ); shmdt( b->shminfo.shmaddr ); shmctl( b->shminfo.shmid, IPC_RMID, 0 ); b->backxrb->ximage = NULL; b->shm = 0; (void) XSetErrorHandler( old_handler ); return GL_FALSE; } shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ /* Finally, try an XShmPutImage to be really sure the extension works */ gc = XCreateGC( b->xm_visual->display, b->frontxrb->drawable, 0, NULL ); XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, gc, b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); XSync( b->xm_visual->display, False ); XFreeGC( b->xm_visual->display, gc ); (void) XSetErrorHandler( old_handler ); if (mesaXErrorFlag) { XFlush( b->xm_visual->display ); mesaXErrorFlag = 0; XDestroyImage( b->backxrb->ximage ); shmdt( b->shminfo.shmaddr ); shmctl( b->shminfo.shmid, IPC_RMID, 0 ); b->backxrb->ximage = NULL; b->shm = 0; return GL_FALSE; } return GL_TRUE;#else /* Can't compile XSHM support */ return GL_FALSE;#endif}#endif/* * Setup an off-screen pixmap or Ximage to use as the back buffer. * Input: b - the X/Mesa buffer */voidxmesa_alloc_back_buffer( XMesaBuffer b, GLuint width, GLuint height ){ if (width == 0 || height == 0) return; if (b->db_mode == BACK_XIMAGE) { /* Deallocate the old backxrb->ximage, if any */ if (b->backxrb->ximage) {#if defined(USE_XSHM) && !defined(XFree86Server) 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; } /* Allocate new back buffer */#ifdef XFree86Server /* Allocate a regular XImage for the back buffer. */ b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel, width, height, NULL); {#else if (b->shm == 0 || !alloc_shm_back_buffer(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 */#endif 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; } else { /* this call just updates the width/origin fields in the xrb */ b->backxrb->Base.AllocStorage(NULL, &b->backxrb->Base, b->backxrb->Base.InternalFormat, b->backxrb->ximage->width, b->backxrb->ximage->height); } } b->backxrb->pixmap = None; } else if (b->db_mode == BACK_PIXMAP) { if (!width) width = 1; if (!height) height = 1; /* Free the old back pixmap */ if (b->backxrb->pixmap) { XMesaFreePixmap( b->xm_visual->display, b->backxrb->pixmap ); } /* 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; }}/* * A replacement for XAllocColor. This function should never * fail to allocate a color. When XAllocColor fails, we return * the nearest matching color. If we have to allocate many colors * this function isn't too efficient; the XQueryColors() could be * done just once. * Written by Michael Pichler, Brian Paul, Mark Kilgard * Input: dpy - X display * cmap - X colormap * cmapSize - size of colormap * In/Out: color - the XColor struct * Output: exact - 1=exact color match, 0=closest match * alloced - 1=XAlloc worked, 0=XAlloc failed */static voidnoFaultXAllocColor( int client, XMesaDisplay *dpy, XMesaColormap cmap, int cmapSize, XMesaColor *color, int *exact, int *alloced ){#ifdef XFree86Server Pixel *ppixIn; xrgb *ctable;#else /* we'll try to cache ctable for better remote display performance */ static Display *prevDisplay = NULL; static XMesaColormap prevCmap = 0; static int prevCmapSize = 0; static XMesaColor *ctable = NULL;#endif XMesaColor subColor; int i, bestmatch; double mindist; /* 3*2^16^2 exceeds long int precision. */ (void) client; /* First try just using XAllocColor. */#ifdef XFree86Server if (AllocColor(cmap, &color->red, &color->green, &color->blue, &color->pixel, client) == Success) {#else if (XAllocColor(dpy, cmap, color)) {#endif *exact = 1; *alloced = 1; return; } /* Alloc failed, search for closest match */ /* Retrieve color table entries. */ /* XXX alloca candidate. */#ifdef XFree86Server ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel)); ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb)); for (i = 0; i < cmapSize; i++) { ppixIn[i] = i; } QueryColors(cmap, cmapSize, ppixIn, ctable);#else if (prevDisplay != dpy || prevCmap != cmap || prevCmapSize != cmapSize || !ctable) { /* free previously cached color table */ if (ctable) _mesa_free(ctable); /* Get the color table from X */ ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); assert(ctable); for (i = 0; i < cmapSize; i++) { ctable[i].pixel = i; } XQueryColors(dpy, cmap, ctable, cmapSize); prevDisplay = dpy; prevCmap = cmap; prevCmapSize = cmapSize; }#endif /* Find best match. */ bestmatch = -1; mindist = 0.0; for (i = 0; i < cmapSize; i++) { double dr = 0.30 * ((double) color->red - (double) ctable[i].red); double dg = 0.59 * ((double) color->green - (double) ctable[i].green); double db = 0.11 * ((double) color->blue - (double) ctable[i].blue); double dist = dr * dr + dg * dg + db * db; if (bestmatch < 0 || dist < mindist) { bestmatch = i; mindist = dist; } } /* Return result. */ subColor.red = ctable[bestmatch].red; subColor.green = ctable[bestmatch].green; subColor.blue = ctable[bestmatch].blue; /* Try to allocate the closest match color. This should only * fail if the cell is read/write. Otherwise, we're incrementing * the cell's reference count. */#ifdef XFree86Server if (AllocColor(cmap, &subColor.red, &subColor.green, &subColor.blue, &subColor.pixel, client) == Success) {#else if (XAllocColor(dpy, cmap, &subColor)) {#endif *alloced = 1; } else { /* do this to work around a problem reported by Frank Ortega */ subColor.pixel = (unsigned long) bestmatch; subColor.red = ctable[bestmatch].red; subColor.green = ctable[bestmatch].green; subColor.blue = ctable[bestmatch].blue; subColor.flags = DoRed | DoGreen | DoBlue; *alloced = 0; }#ifdef XFree86Server _mesa_free(ppixIn); _mesa_free(ctable);#else /* don't free table, save it for next time */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -