+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current X window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * X Resize/StructureNotify events since the X driver has no event loop.
+ * Thus, we poll.
+ * Note that this trick isn't fool-proof. If the application never calls
+ * glViewport, our notion of the current window size may be incorrect.
+ * That problem led to the GLX_MESA_resize_buffers extension.
+ */
+static void
+xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ XMesaContext xmctx = XMESA_CONTEXT(ctx);
+ XMesaBuffer xmdrawbuf = XMESA_BUFFER(ctx->WinSysDrawBuffer);
+ XMesaBuffer xmreadbuf = XMESA_BUFFER(ctx->WinSysReadBuffer);
+ xmesa_check_and_update_buffer_size(xmctx, xmdrawbuf);
+ xmesa_check_and_update_buffer_size(xmctx, xmreadbuf);
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
+}
+
+
+#if ENABLE_EXT_timer_query
+
+/*
+ * The GL_EXT_timer_query extension is not enabled for the XServer
+ * indirect renderer. Not sure about how/if wrapping of gettimeofday()
+ * is done, etc.
+ */
+
+struct xmesa_query_object
+{
+ struct gl_query_object Base;
+ struct timeval StartTime;
+};
+
+
+static struct gl_query_object *
+xmesa_new_query_object(GLcontext *ctx, GLuint id)
+{
+ struct xmesa_query_object *q = CALLOC_STRUCT(xmesa_query_object);
+ if (q) {
+ q->Base.Id = id;
+ q->Base.Ready = GL_TRUE;
+ }
+ return &q->Base;
+}
+
+
+static void
+xmesa_begin_query(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+{
+ if (target == GL_TIME_ELAPSED_EXT) {
+ struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+ (void) gettimeofday(&xq->StartTime, NULL);
+ }
+}
+
+
+/**
+ * Return the difference between the two given times in microseconds.
+ */
+#ifdef __VMS
+#define suseconds_t unsigned int
+#endif
+static GLuint64EXT
+time_diff(const struct timeval *t0, const struct timeval *t1)
+{
+ GLuint64EXT seconds0 = t0->tv_sec & 0xff; /* 0 .. 255 seconds */
+ GLuint64EXT seconds1 = t1->tv_sec & 0xff; /* 0 .. 255 seconds */
+ GLuint64EXT nanosec0 = (seconds0 * 1000000 + t0->tv_usec) * 1000;
+ GLuint64EXT nanosec1 = (seconds1 * 1000000 + t1->tv_usec) * 1000;
+ return nanosec1 - nanosec0;
+}
+
+
+static void
+xmesa_end_query(GLcontext *ctx, GLenum target, struct gl_query_object *q)
+{
+ if (target == GL_TIME_ELAPSED_EXT) {
+ struct xmesa_query_object *xq = (struct xmesa_query_object *) q;
+ struct timeval endTime;
+ (void) gettimeofday(&endTime, NULL);
+ /* result is in nanoseconds! */
+ q->Result = time_diff(&xq->StartTime, &endTime);
+ }
+ q->Ready = GL_TRUE;
+}
+
+#endif /* ENABLE_timer_query */
+
+
+/**
+ * Initialize the device driver function table with the functions
+ * we implement in this driver.
+ */
+void
+xmesa_init_driver_functions( XMesaVisual xmvisual,
+ struct dd_function_table *driver )
+{
+ driver->GetString = get_string;
+ driver->UpdateState = xmesa_update_state;
+ driver->GetBufferSize = NULL; /* OBSOLETE */
+ driver->Flush = finish_or_flush;
+ driver->Finish = finish_or_flush;
+ driver->ClearIndex = clear_index;
+ driver->ClearColor = clear_color;
+ driver->IndexMask = index_mask;
+ driver->ColorMask = color_mask;
+ driver->Enable = enable;
+ driver->Clear = clear_buffers;
+ driver->Viewport = xmesa_viewport;
+#ifndef XFree86Server
+ driver->CopyPixels = xmesa_CopyPixels;
+ if (xmvisual->undithered_pf == PF_8R8G8B &&
+ xmvisual->dithered_pf == PF_8R8G8B) {
+ driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
+ }
+ else if (xmvisual->undithered_pf == PF_5R6G5B) {
+ driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
+ }
+#endif
+ driver->TestProxyTexImage = test_proxy_teximage;
+#if ENABLE_EXT_texure_compression_s3tc
+ driver->ChooseTextureFormat = choose_tex_format;
+#else
+ (void) choose_tex_format;
+#endif
+
+#if ENABLE_EXT_timer_query
+ driver->NewQueryObject = xmesa_new_query_object;
+ driver->BeginQuery = xmesa_begin_query;
+ driver->EndQuery = xmesa_end_query;
+#endif
+}
+
+
+#define XMESA_NEW_POINT (_NEW_POINT | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_LINE (_NEW_LINE | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+
+/**
+ * Extend the software rasterizer with our line/point/triangle
+ * functions.
+ * Called during context creation only.
+ */
+void xmesa_register_swrast_functions( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT( ctx );
+
+ swrast->choose_point = xmesa_choose_point;
+ swrast->choose_line = xmesa_choose_line;
+ swrast->choose_triangle = xmesa_choose_triangle;
+
+ /* XXX these lines have no net effect. Remove??? */
+ swrast->InvalidatePointMask |= XMESA_NEW_POINT;
+ swrast->InvalidateLineMask |= XMESA_NEW_LINE;
+ swrast->InvalidateTriangleMask |= XMESA_NEW_TRIANGLE;