summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/x11/xm_span.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c
index 71a4c800825..6e4bcb18a05 100644
--- a/src/mesa/drivers/x11/xm_span.c
+++ b/src/mesa/drivers/x11/xm_span.c
@@ -3456,6 +3456,47 @@ static void write_pixels_index_ximage( INDEX_PIXELS_ARGS )
/***** Pixel reading *****/
/**********************************************************************/
+#ifndef XFree86Server
+/**
+ * Do clip testing prior to calling XGetImage. If any of the region lies
+ * outside the screen's bounds, XGetImage will return NULL.
+ * We use XTranslateCoordinates() to check if that's the case and
+ * adjust the x, y and length parameters accordingly.
+ * \return -1 if span is totally clipped away,
+ * else return number of pixels to skip in the destination array.
+ */
+static int
+clip_for_xgetimage(XMesaContext xmesa, GLuint *n, GLint *x, GLint *y)
+{
+ XMesaBuffer source = xmesa->xm_buffer;
+ Window rootWin = RootWindow(xmesa->display, 0);
+ Window child;
+ int screenWidth = WidthOfScreen(DefaultScreenOfDisplay(xmesa->display));
+ int dx, dy;
+ XTranslateCoordinates(xmesa->display, source->buffer, rootWin,
+ *x, *y, &dx, &dy, &child);
+ if (dx >= screenWidth) {
+ /* totally clipped on right */
+ return -1;
+ }
+ if (dx < 0) {
+ /* clipped on left */
+ int clip = -dx;
+ if (clip >= *n)
+ return -1; /* totally clipped on left */
+ *x += clip;
+ *n -= clip;
+ dx = 0;
+ return clip;
+ }
+ if (dx + *n > screenWidth) {
+ /* clipped on right */
+ int clip = dx + *n - screenWidth;
+ *n -= clip;
+ }
+ return 0;
+}
+#endif
/*
@@ -3474,6 +3515,11 @@ static void read_index_span( const GLcontext *ctx,
#ifndef XFree86Server
XMesaImage *span = NULL;
int error;
+ int k = clip_for_xgetimage(xmesa, &n, &x, &y);
+ if (k < 0)
+ return;
+ index += k;
+
catch_xgetimage_errors( xmesa->display );
span = XGetImage( xmesa->display, source->buffer,
x, y, n, 1, AllPlanes, ZPixmap );
@@ -3530,9 +3576,15 @@ static void read_color_span( const GLcontext *ctx,
x, FLIP(source, y), n, 1, ZPixmap,
~0L, (pointer)span->data);
#else
+ int k;
+ y = FLIP(source, y);
+ k = clip_for_xgetimage(xmesa, &n, &x, &y);
+ if (k < 0)
+ return;
+ rgba += k;
catch_xgetimage_errors( xmesa->display );
span = XGetImage( xmesa->display, source->buffer,
- x, FLIP(source, y), n, 1, AllPlanes, ZPixmap );
+ x, y, n, 1, AllPlanes, ZPixmap );
error = check_xgetimage_errors();
#endif
if (span && !error) {