- ctx->Driver.GetString = get_string;
- ctx->Driver.GetBufferSize = get_buffer_size;
- ctx->Driver.Flush = flush;
- ctx->Driver.Finish = finish;
-
- /* Hooks for t_vb_render.c:
- */
- ctx->Driver.RenderStart = _swsetup_RenderStart;
- ctx->Driver.RenderFinish = _swsetup_RenderFinish;
- ctx->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
- ctx->Driver.RenderPrimitive = _swsetup_RenderPrimitive;
- ctx->Driver.PointsFunc = _swsetup_Points;
- ctx->Driver.LineFunc = _swsetup_Line;
- ctx->Driver.TriangleFunc = _swsetup_Triangle;
- ctx->Driver.QuadFunc = _swsetup_Quad;
- ctx->Driver.ResetLineStipple = _swrast_ResetLineStipple;
- ctx->Driver.RenderInterp = _swsetup_RenderInterp;
- ctx->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
- ctx->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
- ctx->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
-
- /* Software rasterizer pixel paths:
- */
- ctx->Driver.Accum = _swrast_Accum;
- ctx->Driver.Bitmap = _swrast_Bitmap;
- ctx->Driver.Clear = clear_buffers;
- ctx->Driver.ResizeBuffersMESA = resize_buffers;
- ctx->Driver.CopyPixels = _swrast_CopyPixels;
- ctx->Driver.DrawPixels = _swrast_DrawPixels;
- ctx->Driver.ReadPixels = _swrast_ReadPixels;
-
- /* Software texture functions:
- */
- ctx->Driver.TexImage1D = _mesa_store_teximage1d;
- ctx->Driver.TexImage2D = _mesa_store_teximage2d;
- ctx->Driver.TexImage3D = _mesa_store_teximage3d;
- ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
- ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
- ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
- ctx->Driver.CopyTexImage1D = _mesa_copy_teximage1d;
- ctx->Driver.CopyTexImage2D = _mesa_copy_teximage2d;
- ctx->Driver.CopyTexSubImage1D = _mesa_copy_texsubimage1d;
- ctx->Driver.CopyTexSubImage2D = _mesa_copy_texsubimage2d;
- ctx->Driver.CopyTexSubImage3D = _mesa_copy_texsubimage3d;
- ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
-
- /*
- */
- ctx->Driver.SetDrawBuffer = set_draw_buffer;
- ctx->Driver.SetReadBuffer = set_read_buffer;
- ctx->Driver.ClearIndex = clear_index;
- ctx->Driver.ClearColor = clear_color;
- ctx->Driver.IndexMask = index_mask;
- ctx->Driver.ColorMask = color_mask;
- ctx->Driver.Enable = enable;
-
- (void) DitherValues; /* silenced unused var warning */
+ if (target == GL_PROXY_TEXTURE_3D) {
+ /* special case for 3D textures */
+ if (width * height * depth > 512 * 512 * 64 ||
+ width < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(width - 2 * border) != 1) ||
+ height < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(height - 2 * border) != 1) ||
+ depth < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(depth - 2 * border) != 1)) {
+ /* Bad size, or too many texels */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ }
+ else {
+ /* use the fallback routine for 1D, 2D, cube and rect targets */
+ return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
+ format, type, width, height, depth,
+ border);
+ }
+}
+
+
+/**
+ * In SW, we don't really compress GL_COMPRESSED_RGB[A] textures!
+ */
+static const struct gl_texture_format *
+choose_tex_format( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_ARB:
+ return &_mesa_texformat_rgb;
+ case GL_COMPRESSED_RGBA_ARB:
+ return &_mesa_texformat_rgba;
+ default:
+ return _mesa_choose_tex_format(ctx, internalFormat, format, type);
+ }
+}
+
+
+/**
+ * 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;