/** * Reallocate renderbuffer storage for back color buffer. * Called via gl_renderbuffer::AllocStorage() */ static GLboolean xmesa_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); /* reallocate the back buffer XImage or Pixmap */ assert(xrb->Parent); alloc_back_buffer(xrb->Parent, width, height); /* same as front buffer */ /* XXX why is this here? */ (void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height); /* plus... */ if (xrb->ximage) { /* Needed by PIXELADDR1 macro */ xrb->width1 = xrb->ximage->bytes_per_line; xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1); /* Needed by PIXELADDR2 macro */ xrb->width2 = xrb->ximage->bytes_per_line / 2; xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1); /* Needed by PIXELADDR3 macro */ xrb->width3 = xrb->ximage->bytes_per_line; xrb->origin3 = (GLubyte *) xrb->ximage->data + xrb->width3 * (height - 1); /* Needed by PIXELADDR4 macro */ xrb->width4 = xrb->ximage->width; xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1); } else { /* out of memory or buffer size is 0 x 0 */ xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0; xrb->origin1 = NULL; xrb->origin2 = NULL; xrb->origin3 = NULL; xrb->origin4 = NULL; } return GL_TRUE; }
/** * Reallocate renderbuffer storage for front color buffer. * Called via gl_renderbuffer::AllocStorage() */ static GLboolean xmesa_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); /* just clear these to be sure we don't accidentally use them */ xrb->origin2 = NULL; xrb->origin3 = NULL; xrb->origin4 = NULL; /* for the FLIP macro: */ xrb->bottom = height - 1; rb->Width = width; rb->Height = height; rb->InternalFormat = internalFormat; return GL_TRUE; }
/** * Called via ctx->Driver.UnmapRenderbuffer() */ void xmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) { XImage *ximage = xrb->ximage; if (!ximage) { /* this must be a pixmap/window renderbuffer */ assert(xrb->pixmap); assert(xrb->map_ximage); if (xrb->map_ximage) { if (xrb->map_mode & GL_MAP_WRITE_BIT) { /* put modified ximage data back into the pixmap/window */ int y2 = rb->Height - xrb->map_y - xrb->map_h; GC gc = XCreateGC(xrb->Parent->display, xrb->pixmap, 0, NULL); XPutImage(xrb->Parent->display, xrb->pixmap, /* dest */ gc, xrb->map_ximage, /* source */ 0, 0, /* src x, y */ xrb->map_x, y2, /* dest x, y */ xrb->map_w, xrb->map_h); /* size */ XFreeGC(xrb->Parent->display, gc); } XMesaDestroyImage(xrb->map_ximage); xrb->map_ximage = NULL; } } xrb->map_mode = 0x0; return; } /* otherwise, this is an ordinary malloc-based renderbuffer */ _swrast_unmap_soft_renderbuffer(ctx, rb); }
/* * Return the depth buffer associated with an XMesaBuffer. * Input: b - the XMesa buffer handle * Output: width, height - size of buffer in pixels * bytesPerValue - bytes per depth value (2 or 4) * buffer - pointer to depth buffer values * Return: GL_TRUE or GL_FALSE to indicate success or failure. */ GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, GLint *bytesPerValue, void **buffer ) { struct gl_renderbuffer *rb = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); if (!xrb || !xrb->Base.Buffer) { *width = 0; *height = 0; *bytesPerValue = 0; *buffer = 0; return GL_FALSE; } else { *width = b->mesa_buffer.Width; *height = b->mesa_buffer.Height; *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 ? sizeof(GLushort) : sizeof(GLuint); *buffer = (void *) xrb->Base.Buffer; return GL_TRUE; } }
/** * Return pointer to line drawing function, or NULL if we should use a * swrast fallback. */ static swrast_tri_func get_triangle_func(struct gl_context *ctx) { #if CHAN_BITS == 8 SWcontext *swrast = SWRAST_CONTEXT(ctx); XMesaContext xmesa = XMESA_CONTEXT(ctx); const struct xmesa_renderbuffer *xrb; #ifdef DEBUG triFuncName = NULL; #endif /* trivial fallback tests */ if ((ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_FRONT_LEFT) && (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_BACK_LEFT)) 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; xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); 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); 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); 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); 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); default: return (swrast_tri_func) NULL; } } } #endif /* CHAN_BITS == 8 */ return (swrast_tri_func) NULL; }
/** * Return pointer to line drawing function, or NULL if we should use a * swrast fallback. */ static swrast_line_func get_line_func(struct gl_context *ctx) { #if CHAN_BITS == 8 SWcontext *swrast = SWRAST_CONTEXT(ctx); XMesaContext xmesa = XMESA_CONTEXT(ctx); const struct xmesa_renderbuffer *xrb; if ((ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_FRONT_LEFT) && (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_BACK_LEFT)) return (swrast_line_func) NULL; if (ctx->RenderMode != GL_RENDER) return (swrast_line_func) NULL; if (ctx->Line.SmoothFlag) return (swrast_line_func) NULL; if (ctx->Texture._MaxEnabledTexImageUnit != -1) return (swrast_line_func) NULL; if (ctx->Light.ShadeModel != GL_FLAT) return (swrast_line_func) NULL; if (ctx->Line.StippleFlag) return (swrast_line_func) NULL; if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL; xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]); if (xrb->ximage && swrast->_RasterMask==DEPTH_BIT && ctx->Depth.Func==GL_LESS && ctx->Depth.Mask==GL_TRUE && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS && ctx->Line.Width==1.0F) { switch (xmesa->pixelformat) { case PF_Truecolor: return flat_TRUECOLOR_z_line; case PF_8A8B8G8R: return flat_8A8B8G8R_z_line; case PF_8A8R8G8B: return flat_8A8R8G8B_z_line; case PF_8R8G8B: return flat_8R8G8B_z_line; case PF_8R8G8B24: return flat_8R8G8B24_z_line; case PF_5R6G5B: return flat_5R6G5B_z_line; case PF_Dither_5R6G5B: return flat_DITHER_5R6G5B_z_line; default: return (swrast_line_func)NULL; } } if (xrb->ximage && swrast->_RasterMask==0 && ctx->Line.Width==1.0F) { switch (xmesa->pixelformat) { case PF_Truecolor: return flat_TRUECOLOR_line; case PF_8A8B8G8R: return flat_8A8B8G8R_line; case PF_8A8R8G8B: return flat_8A8R8G8B_line; case PF_8R8G8B: return flat_8R8G8B_line; case PF_8R8G8B24: return flat_8R8G8B24_line; case PF_5R6G5B: return flat_5R6G5B_line; case PF_Dither_5R6G5B: return flat_DITHER_5R6G5B_line; default: return (swrast_line_func)NULL; } } if (ctx->DrawBuffer->_NumColorDrawBuffers == 1 && ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT && swrast->_RasterMask == LOGIC_OP_BIT && ctx->Color.LogicOp == GL_XOR && !ctx->Line.StippleFlag && !ctx->Line.SmoothFlag) { return xor_line; } #endif /* CHAN_BITS == 8 */ return (swrast_line_func) NULL; }
/** * Called via ctx->Driver.MapRenderbuffer() */ void xmesa_MapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint x, GLuint y, GLuint w, GLuint h, GLbitfield mode, GLubyte **mapOut, GLint *rowStrideOut) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) { XImage *ximage = xrb->ximage; assert(!xrb->map_mode); /* only a single mapping allowed */ xrb->map_mode = mode; xrb->map_x = x; xrb->map_y = y; xrb->map_w = w; xrb->map_h = h; if (ximage) { int y2 = rb->Height - y - 1; *mapOut = (GLubyte *) ximage->data + y2 * ximage->bytes_per_line + x * ximage->bits_per_pixel / 8; } else { /* this must be a pixmap/window renderbuffer */ int (*old_handler)(XMesaDisplay *, XErrorEvent *); int y2 = rb->Height - y - h; assert(xrb->pixmap); /* Install error handler for XGetImage() in case the the window * isn't mapped. If we fail we'll create a temporary XImage. */ mesaXErrorFlag = 0; old_handler = XSetErrorHandler(mesaHandleXError); /* read pixel data out of the pixmap/window into an XImage */ ximage = XGetImage(xrb->Parent->display, xrb->pixmap, x, y2, w, h, AllPlanes, ZPixmap); XSetErrorHandler(old_handler); if (mesaXErrorFlag) { /* create new, temporary XImage */ int bytes_per_line = _mesa_format_row_stride(xrb->Base.Base.Format, xrb->Base.Base.Width); char *image = (char *) malloc(bytes_per_line * xrb->Base.Base.Height); ximage = XCreateImage(xrb->Parent->display, xrb->Parent->xm_visual->visinfo->visual, xrb->Parent->xm_visual->visinfo->depth, ZPixmap, /* format */ 0, /* offset */ image, /* data */ xrb->Base.Base.Width, xrb->Base.Base.Height, 8, /* pad */ bytes_per_line); } if (!ximage) { *mapOut = NULL; *rowStrideOut = 0; return; } xrb->map_ximage = ximage; /* the first row of the OpenGL image is last row of the XImage */ *mapOut = (GLubyte *) ximage->data + (h - 1) * ximage->bytes_per_line; } /* We return a negative stride here since XImage data is upside down * with respect to OpenGL images. */ *rowStrideOut = -ximage->bytes_per_line; return; } /* otherwise, this is an ordinary malloc-based renderbuffer */ _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode, mapOut, rowStrideOut); }
/** * Called via ctx->Driver.MapRenderbuffer() */ void xmesa_MapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint x, GLuint y, GLuint w, GLuint h, GLbitfield mode, GLubyte **mapOut, GLint *rowStrideOut) { struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); if (xrb->Base.Base.ClassID == XMESA_RENDERBUFFER) { XImage *ximage = xrb->ximage; assert(!xrb->map_mode); /* only a single mapping allowed */ xrb->map_mode = mode; xrb->map_x = x; xrb->map_y = y; xrb->map_w = w; xrb->map_h = h; if (ximage) { int y2 = rb->Height - y - 1; *mapOut = (GLubyte *) ximage->data + y2 * ximage->bytes_per_line + x * ximage->bits_per_pixel / 8; } else { /* this must be a pixmap/window renderbuffer */ int y2 = rb->Height - y - h; assert(xrb->pixmap); /* read pixel data out of the pixmap/window into an XImage */ ximage = XGetImage(xrb->Parent->display, xrb->pixmap, x, y2, w, h, AllPlanes, ZPixmap); if (!ximage) { *mapOut = NULL; *rowStrideOut = 0; return; } xrb->map_ximage = ximage; /* the first row of the OpenGL image is last row of the XImage */ *mapOut = (GLubyte *) ximage->data + (h - 1) * ximage->bytes_per_line; } /* We return a negative stride here since XImage data is upside down * with respect to OpenGL images. */ *rowStrideOut = -ximage->bytes_per_line; return; } /* otherwise, this is an ordinary malloc-based renderbuffer */ _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode, mapOut, rowStrideOut); }
PUBLIC void XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer, const int *attrib_list) { #if 0 GET_CURRENT_CONTEXT(ctx); const GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; struct gl_texture_object *texObj; #endif struct gl_renderbuffer *rb; struct xmesa_renderbuffer *xrb; GLint b; XMesaImage *img = NULL; GLboolean freeImg = GL_FALSE; b = xbuffer_to_renderbuffer(buffer); if (b < 0) return; if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) return; /* BadMatch error */ rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; if (!rb) { /* invalid buffer */ return; } xrb = xmesa_renderbuffer(rb); #if 0 switch (drawable->TextureTarget) { case GLX_TEXTURE_1D_EXT: texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX]; break; case GLX_TEXTURE_2D_EXT: texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX]; break; case GLX_TEXTURE_RECTANGLE_EXT: texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX]; break; default: return; /* BadMatch error */ } #endif /* * The following is a quick and simple way to implement * BindTexImage. The better way is to write some new FetchTexel() * functions which would extract texels from XImages. We'd still * need to use GetImage when texturing from a Pixmap (front buffer) * but texturing from a back buffer (XImage) would avoid an image * copy. */ /* get XImage */ if (xrb->pixmap) { img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L, ZPixmap); freeImg = GL_TRUE; } else if (xrb->ximage) { img = xrb->ximage; } /* store the XImage as a new texture image */ if (img) { GLenum format, type, intFormat; if (img->bits_per_pixel == 32) { format = GL_BGRA; type = GL_UNSIGNED_BYTE; intFormat = GL_RGBA; } else if (img->bits_per_pixel == 24) { format = GL_BGR; type = GL_UNSIGNED_BYTE; intFormat = GL_RGB; } else if (img->bits_per_pixel == 16) { format = GL_BGR; type = GL_UNSIGNED_SHORT_5_6_5; intFormat = GL_RGB; } else { _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); return; } if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { intFormat = GL_RGBA; } else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { intFormat = GL_RGB; } _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, format, type, img->data); if (freeImg) { XMesaDestroyImage(img); } } }