Bug#241331: fix libGL builds on sparc
Attached is a patch stolen from xfree86's bugzilla (#923).
I've rediffed it, to fit into 4.3.0-7. Builds fine on sparc, and glx
apps are fine with indirect mesa rendering again.
(to get dri working with sunffb - fails initialization due to a missing
symbol - is another story; I will open a new bug for it sometime, after
testing a little fix discussed with DaveM)
The corresponding upstream changeset can be found at:
http://cvsweb.xfree86.org/cvsweb/xc/lib/GL/glx/glxext.c.diff?r1=1.21&r2=1.22
I don't see any problematic license changes in it.
Please apply.
- Christian
--- xc/lib/GL/glx/glxext.c.orig 2003-02-21 06:31:24.000000000 +0100
+++ xc/lib/GL/glx/glxext.c 2004-04-06 00:05:43.000000000 +0200
@@ -58,6 +58,37 @@
void __glXDumpDrawBuffer(__GLXcontext *ctx);
#endif
+#ifdef USE_SPARC_ASM
+/*
+ * This is where our dispatch table's bounds are.
+ * And the static mesa_init is taken directly from
+ * Mesa's 'sparc.c' initializer.
+ *
+ * We need something like this here, because this version
+ * of openGL/glx never initializes a Mesa context, and so
+ * the address of the dispatch table pointer never gets stuffed
+ * into the dispatch jump table otherwise.
+ *
+ * It matters only on SPARC, and only if you are using assembler
+ * code instead of C-code indirect dispatch.
+ *
+ * -- FEM, 04.xii.03
+ */
+extern unsigned int _mesa_sparc_glapi_begin;
+extern unsigned int _mesa_sparc_glapi_end;
+extern void __glapi_sparc_icache_flush(unsigned int *);
+static void _glx_mesa_init_sparc_glapi_relocs(void);
+static int _mesa_sparc_needs_init = 1;
+#define INIT_MESA_SPARC { \
+ if(_mesa_sparc_needs_init) { \
+ _glx_mesa_init_sparc_glapi_relocs(); \
+ _mesa_sparc_needs_init = 0; \
+ } \
+}
+#else
+#define INIT_MESA_SPARC
+#endif
+
/*
** We setup some dummy structures here so that the API can be used
** even if no context is current.
@@ -489,6 +520,7 @@
}
#endif
+ INIT_MESA_SPARC
/* The one and only long long lock */
__glXLock();
@@ -603,6 +635,7 @@
if (gc->currentDpy == dpy) {
/* Use opcode from gc because its right */
+ INIT_MESA_SPARC
return gc->majorOpcode;
} else {
/*
@@ -1029,3 +1062,64 @@
}
}
#endif
+
+/*
+ * Used only when we are sparc, using sparc assembler.
+ *
+ */
+
+static void
+_glx_mesa_init_sparc_glapi_relocs(void)
+{
+#ifdef USE_SPARC_ASM
+ unsigned int *insn_ptr, *end_ptr;
+ unsigned long disp_addr;
+
+ insn_ptr = &_mesa_sparc_glapi_begin;
+ end_ptr = &_mesa_sparc_glapi_end;
+ disp_addr = (unsigned long) &_glapi_Dispatch;
+
+ /*
+ * Verbatim from Mesa sparc.c. It's needed because there doesn't
+ * seem to be a better way to do this:
+ *
+ * UNCONDITIONAL_JUMP ( (*_glapi_Dispatch) + entry_offset )
+ *
+ * This code is patching in the ADDRESS of the pointer to the
+ * dispatch table. Hence, it must be called exactly once, because
+ * that address is not going to change.
+ *
+ * What it points to can change, but Mesa (and hence, we) assume
+ * that there is only one pointer.
+ *
+ */
+ while (insn_ptr < end_ptr) {
+#if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) )
+/*
+ This code patches for 64-bit addresses. This had better
+ not happen for Sparc/Linux, no matter what architecture we
+ are building for. So, don't do this.
+
+ The 'defined(__linux_64__)' is used here as a placeholder for
+ when we do do 64-bit usermode on sparc linux.
+ */
+ insn_ptr[0] |= (disp_addr >> (32 + 10));
+ insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10);
+ __glapi_sparc_icache_flush(&insn_ptr[0]);
+ insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1));
+ insn_ptr[3] |= (disp_addr & ((1 << 10) - 1));
+ __glapi_sparc_icache_flush(&insn_ptr[2]);
+ insn_ptr += 11;
+#else
+ insn_ptr[0] |= (disp_addr >> 10);
+ insn_ptr[1] |= (disp_addr & ((1 << 10) - 1));
+ __glapi_sparc_icache_flush(&insn_ptr[0]);
+ insn_ptr += 5;
+#endif
+#else
+ /* Just no-op
+ *
+ */
+#endif /* sparc ASM in use */
+ }
+}
Reply to: