summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2003-11-29 19:36:08 +0000
committerBrian Paul <brian.paul@tungstengraphics.com>2003-11-29 19:36:08 +0000
commitde0dd65aeec33284019a766ac113028cf9bffe5b (patch)
tree5eb7f702b560715080bf373a68b7a503f5a68b91
parente90de7883a3bd9afd27ac83314f08cf9f03f60e3 (diff)
Use XPutImage() for glDrawPixels() and XCopyArea() for glCopyPixels() when
possible (when pixel formats match and drawing to front buffer with no raster operations). Results in 10-100x speed-up when applicable.
-rw-r--r--src/mesa/drivers/x11/xm_dd.c200
1 files changed, 172 insertions, 28 deletions
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
index 28e6154df4..d82edda774 100644
--- a/src/mesa/drivers/x11/xm_dd.c
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -40,8 +40,9 @@
#include "texformat.h"
#include "xmesaP.h"
#include "array_cache/acache.h"
-#include "swrast/s_context.h"
#include "swrast/swrast.h"
+#include "swrast/s_context.h"
+#include "swrast/s_drawpix.h"
#include "swrast/s_alphabuf.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
@@ -760,61 +761,194 @@ xmesa_resize_buffers( GLframebuffer *buffer )
_swrast_alloc_buffers( buffer );
}
-#if 0
-/*
+
+/**
* This function implements glDrawPixels() with an XPutImage call when
* drawing to the front buffer (X Window drawable).
* The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
- * XXX top/bottom edge clipping is broken!
*/
-static GLboolean
-drawpixels_8R8G8B( GLcontext *ctx,
- GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type,
- const struct gl_pixelstore_attrib *unpack,
- const GLvoid *pixels )
+static void
+xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
{
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
XMesaDisplay *dpy = xmesa->xm_visual->display;
- XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
- XMesaGC gc = xmesa->xm_draw_buffer->gc;
- assert(dpy);
- assert(buffer);
- assert(gc);
-
- /* XXX also check for pixel scale/bias/lookup/zooming! */
- if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
+ const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+ ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
+ ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
+
+ if (buffer && /* buffer != 0 means it's a Window or Pixmap */
+ format == GL_BGRA &&
+ type == GL_UNSIGNED_BYTE &&
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
int dstX = x;
int dstY = y;
int w = width;
int h = height;
int srcX = unpack->SkipPixels;
int srcY = unpack->SkipRows;
- if (_mesa_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ int rowLength = unpack->RowLength ? unpack->RowLength : width;
+ if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ /* This is a little tricky since all coordinates up to now have
+ * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
+ * so we have to carefully compute the Y coordinates/addresses here.
+ */
XMesaImage ximage;
MEMSET(&ximage, 0, sizeof(XMesaImage));
ximage.width = width;
ximage.height = height;
ximage.format = ZPixmap;
- ximage.data = (char *) pixels + (height - 1) * width * 4;
+ ximage.data = (char *) pixels
+ + ((srcY + h - 1) * rowLength + srcX) * 4;
ximage.byte_order = LSBFirst;
ximage.bitmap_unit = 32;
ximage.bitmap_bit_order = LSBFirst;
ximage.bitmap_pad = 32;
ximage.depth = 24;
- ximage.bytes_per_line = -width * 4;
+ ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
ximage.bits_per_pixel = 32;
ximage.red_mask = 0xff0000;
ximage.green_mask = 0x00ff00;
ximage.blue_mask = 0x0000ff;
- dstY = FLIP(xmesa->xm_draw_buffer,dstY) - height + 1;
- XPutImage(dpy, buffer, gc, &ximage, srcX, srcY, dstX, dstY, w, h);
- return GL_TRUE;
+ /* flip Y axis for dest position */
+ dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
+ XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
}
}
- return GL_FALSE;
+ else {
+ /* software fallback */
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ }
+}
+
+
+
+/**
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable). The image format
+ * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
+ * match the PF_5R6G5B pixel format.
+ */
+static void
+xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+ ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
+
+ if (buffer && /* buffer != 0 means it's a Window or Pixmap */
+ format == GL_RGB &&
+ type == GL_UNSIGNED_SHORT_5_6_5 &&
+ !ctx->Color.DitherFlag && /* no dithering */
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
+ int dstX = x;
+ int dstY = y;
+ int w = width;
+ int h = height;
+ int srcX = unpack->SkipPixels;
+ int srcY = unpack->SkipRows;
+ int rowLength = unpack->RowLength ? unpack->RowLength : width;
+ if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ /* This is a little tricky since all coordinates up to now have
+ * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
+ * so we have to carefully compute the Y coordinates/addresses here.
+ */
+ XMesaImage ximage;
+ MEMSET(&ximage, 0, sizeof(XMesaImage));
+ ximage.width = width;
+ ximage.height = height;
+ ximage.format = ZPixmap;
+ ximage.data = (char *) pixels
+ + ((srcY + h - 1) * rowLength + srcX) * 2;
+ ximage.byte_order = LSBFirst;
+ ximage.bitmap_unit = 32;
+ ximage.bitmap_bit_order = LSBFirst;
+ ximage.bitmap_pad = 32;
+ ximage.depth = 16;
+ ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
+ ximage.bits_per_pixel = 16;
+ ximage.red_mask = 0xff0000;
+ ximage.green_mask = 0x00ff00;
+ ximage.blue_mask = 0x0000ff;
+ /* flip Y axis for dest position */
+ dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
+ XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
+ }
+ }
+ else {
+ /* software fallback */
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ }
}
-#endif
+
+
+
+/**
+ * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
+ * for the color buffer. Don't support zooming, pixel transfer, etc.
+ * We do support copying from one window to another, ala glXMakeCurrentRead.
+ */
+static void
+xmesa_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLint destx, GLint desty, GLenum type )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+
+ if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
+ readBuffer &&
+ type == GL_COLOR &&
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
+ /* Note: we don't do any special clipping work here. We could,
+ * but X will do it for us.
+ */
+ srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
+ desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
+ XCopyArea(dpy, readBuffer, drawBuffer, gc,
+ srcx, srcy, width, height, destx, desty);
+ }
+ else {
+ _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
+ }
+}
+
/*
@@ -961,6 +1095,7 @@ void xmesa_init_pointers( GLcontext *ctx )
{
TNLcontext *tnl;
struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference( ctx );
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
/* Plug in our driver-specific functions here */
ctx->Driver.GetString = get_string;
@@ -979,8 +1114,17 @@ void xmesa_init_pointers( GLcontext *ctx )
ctx->Driver.Bitmap = _swrast_Bitmap;
ctx->Driver.Clear = clear_buffers;
ctx->Driver.ResizeBuffers = xmesa_resize_buffers;
- ctx->Driver.CopyPixels = _swrast_CopyPixels;
- ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.CopyPixels = xmesa_CopyPixels;
+ if (xmesa->xm_visual->undithered_pf == PF_8R8G8B &&
+ xmesa->xm_visual->dithered_pf == PF_8R8G8B) {
+ ctx->Driver.DrawPixels = xmesa_DrawPixels_8R8G8B;
+ }
+ else if (xmesa->xm_visual->undithered_pf == PF_5R6G5B) {
+ ctx->Driver.DrawPixels = xmesa_DrawPixels_5R6G5B;
+ }
+ else {
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ }
ctx->Driver.ReadPixels = _swrast_ReadPixels;
ctx->Driver.DrawBuffer = _swrast_DrawBuffer;