aboutsummaryrefslogtreecommitdiff
path: root/generic/tkZinc.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkZinc.c')
-rw-r--r--generic/tkZinc.c295
1 files changed, 209 insertions, 86 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c
index 736cebd..f014aee 100644
--- a/generic/tkZinc.c
+++ b/generic/tkZinc.c
@@ -49,7 +49,6 @@ static const char * const zinc_version = "zinc-version-" VERSION;
#include "perfos.h"
#endif
-#include <GL/glu.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
@@ -59,6 +58,10 @@ static const char * const zinc_version = "zinc-version-" VERSION;
#if defined(_WIN32) && defined(PTK) && !defined(PTK_800)
#include <tkPlatDecls.m>
#endif
+#if defined(MAC_OSX_TK) && defined(GL)
+#include <tkMacOSX.h>
+#include <tkMacOSXInt.h>
+#endif
typedef struct _TagSearchExpr {
@@ -123,7 +126,18 @@ static Tk_Uid star_uid;
#ifdef GL
static ZnGLContextEntry *gl_contexts = NULL;
-#ifndef _WIN32
+#if defined(MAC_OSX_TK)
+static GLint ZnGLAttribs[] = {
+ AGL_RGBA,
+ AGL_DOUBLEBUFFER,
+ AGL_RED_SIZE, 8,
+ AGL_GREEN_SIZE, 8,
+ AGL_BLUE_SIZE, 8,
+ AGL_STENCIL_SIZE, 8,
+ AGL_DEPTH_SIZE, 0,
+ AGL_NONE
+};
+#elif !defined(_WIN32)
static int ZnMajorGlx, ZnMinorGlx;
static int ZnGLAttribs[] = {
GLX_RGBA,
@@ -900,19 +914,37 @@ ZnNeedRedisplay(ZnWInfo *wi)
*
* ZnGetGlContext --
*
+ * On AGL there is one context per window/widget. The Oldest context
+ * is used to share the resources until it is destroyed, this task is
+ * then transferred to the next older and so on.
+ * On the other platforms a single context is created and shared
+ * amongst all the windows for a sinlge display.
+ *
*----------------------------------------------------------------------
*/
#ifdef GL
ZnGLContextEntry *
ZnGetGLContext(Display *dpy)
{
- ZnGLContextEntry *context_entry;
+ ZnGLContextEntry *cur, *last;
- for (context_entry = gl_contexts;
- context_entry && context_entry->dpy != dpy;
- context_entry = context_entry->next);
+ //
+ // Find the first context matching.
+ for (cur = gl_contexts; cur && cur->dpy != dpy; cur = cur->next);
+
+ if (!cur) {
+ return cur;
+ }
- return context_entry;
+ //
+ // Now proceed to the oldest.
+ for (last = cur; cur->next; cur = cur->next) {
+ if (cur->dpy == dpy) {
+ last = cur;
+ }
+ }
+
+ return last;
}
ZnGLContextEntry *
@@ -954,6 +986,10 @@ ZnGLMakeCurrent(Display *dpy,
if (!wglMakeCurrent(ce->hdc, ce->context)) {
fprintf(stderr, "Can't make the GL context current: %d\n", GetLastError());
}
+#elif defined(MAC_OSX_TK)
+ if (aglSetCurrentContext(ce->context) == GL_FALSE) {
+ fprintf(stderr, "Can't make the GL context current\n");
+ }
#else
glXMakeCurrent(dpy, Tk_WindowId(wi->win), ce->context);
#endif
@@ -980,6 +1016,8 @@ ZnGLSwapBuffers(ZnGLContextEntry *ce,
if (ce) {
#ifdef _WIN32
SwapBuffers(ce->hdc);
+#elif defined(MAC_OSX_TK)
+ aglSwapBuffers(ce->context);
#else
glXSwapBuffers(ce->dpy, Tk_WindowId(wi->win));
#endif
@@ -994,8 +1032,8 @@ InitRendering1(ZnWInfo *wi)
{
if (wi->render) {
-# ifndef _WIN32
- ZnGLContextEntry *ce;
+# if !defined(_WIN32) && !defined(MAC_OSX_TK)
+ ZnGLContextEntry *ce;
ZnGLContext gl_context;
XVisualInfo *gl_visual = NULL;
Colormap colormap = 0;
@@ -1075,24 +1113,45 @@ InitRendering1(ZnWInfo *wi)
if (gl_visual && colormap) {
Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap);
}
-# endif /* _WIN32 */
+# endif
}
}
+#if defined(MAC_OSX_TK)
static void
-InitRendering2(ZnWInfo *wi)
+UpdateBufferRect(ZnGLContextEntry *ce,
+ Tk_Window win)
{
- ZnGLContextEntry *ce;
- ZnGLContext gl_context;
- GLfloat r[2]; /* Min, Max */
- GLint i[1];
+ GLint rect[4];
+ Rect bounds;
+
+ TkMacOSXWinBounds((TkWindow *) win, &bounds);
+ rect[0] = bounds.left;
+ rect[1] = Tk_Height(ce->top_win) - bounds.bottom;
+ rect[2] = bounds.right - bounds.left;
+ rect[3] = bounds.bottom - bounds.top;;
+ //printf("BUFFER_RECT: %d %d %d %d\n", rect[0], rect[1], rect[2], rect[3]);
+ aglSetInteger(ce->context, AGL_BUFFER_RECT, rect);
+ aglEnable(ce->context, AGL_BUFFER_RECT);
+}
+#endif
+
+static void
+InitRendering2(ZnWInfo *wi,
+ Tk_Window top_level)
+{
+ ZnGLContextEntry *ce;
+ ZnGLContext gl_context;
+ GLfloat r[2]; /* Min, Max */
+ GLint i[1];
if (wi->render) {
-# ifdef _WIN32
/*
* Look for a matching context already available.
*/
ce = ZnGetGLContext(wi->dpy);
+
+# ifdef _WIN32
if (ce) {
gl_context = ce->context;
ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
@@ -1151,6 +1210,48 @@ InitRendering2(ZnWInfo *wi)
}
}
ReleaseDC(ce->hwnd, ce->hdc);
+
+#elif defined(MAC_OSX_TK)
+
+ {
+ AGLPixelFormat pix_fmt;
+ GLenum err;
+
+ pix_fmt = aglChoosePixelFormat(NULL, 0, ZnGLAttribs);
+ err = aglGetError();
+ if (pix_fmt && (err == AGL_NO_ERROR)) {
+ gl_context = aglCreateContext(pix_fmt, ce ? ce->context : NULL);
+ err = aglGetError();
+ }
+ else {
+ fprintf(stderr, "error when selecting a pixel format 0x%x %d\n", pix_fmt, err);
+ return;
+ }
+ if ((err != AGL_NO_ERROR) || (gl_context == NULL)) {
+ fprintf(stderr, "No GL context\n");
+ return;
+ }
+ else {
+ ce = ZnMalloc(sizeof(ZnGLContextEntry));
+ ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
+ ZnListAdd(ce->widgets, &wi, ZnListTail);
+
+ ce->context = gl_context;
+ ce->dpy = wi->dpy;
+ ce->max_tex_size = 64; /* Minimum value is always valid */
+ ce->max_line_width = 1;
+ ce->max_point_width = 1;
+ ce->next = gl_contexts;
+ gl_contexts = ce;
+ ce->pix_fmt = pix_fmt;
+ ce->gworld = TkMacOSXGetDrawablePort(Tk_WindowId(wi->win));
+ ce->top_win = top_level;
+ if (aglSetDrawable(ce->context, ce->gworld) == GL_FALSE) {
+ fprintf(stderr, "Can't attach the window to the GL context\n");
+ }
+ }
+ }
+
#endif
ce = ZnGLMakeCurrent(wi->dpy, wi);
@@ -1178,6 +1279,9 @@ InitRendering2(ZnWInfo *wi)
ce->max_tex_size);
}
+#if defined(MAC_OSX_TK)
+ UpdateBufferRect(ce, wi->win);
+#endif
ZnGLReleaseContext(ce);
}
}
@@ -1209,7 +1313,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with
#endif
unsigned int num;
ZnBool has_gl = False;
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(MAC_OSX_TK)
# if defined(GL) || defined(SHAPE)
int major_op, first_err, first_evt;
# endif
@@ -1222,7 +1326,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with
InitZinc(interp);
#ifdef GL
-# ifdef _WIN32
+# if defined(_WIN32) || defined(MAC_OSX_TK)
has_gl = True;
# else
if (XQueryExtension(dpy, "GLX", &major_op, &first_evt, &first_err)) {
@@ -1287,7 +1391,7 @@ ZincObjCmd(ClientData client_data, /* Main window associated with
wi->real_top = None;
ASSIGN(wi->flags, ZN_HAS_GL, has_gl);
-#if defined(SHAPE) && !defined(_WIN32)
+#if defined(SHAPE)
ASSIGN(wi->flags, ZN_HAS_X_SHAPE,
XQueryExtension(wi->dpy, "SHAPE", &major_op, &first_evt, &first_err));
wi->reshape = wi->full_reshape = True;
@@ -2643,7 +2747,7 @@ LayoutItems(ZnWInfo *wi,
/*
*----------------------------------------------------------------------
*
- * SetOrigin --
+ * ZnSetOrigin --
*
* This procedure is invoked to translate the viewed area so
* that the given point is displayed in the top left corner.
@@ -2661,9 +2765,9 @@ LayoutItems(ZnWInfo *wi,
*----------------------------------------------------------------------
*/
static void
-SetOrigin(ZnWInfo *wi,
- ZnReal x_origin,
- ZnReal y_origin)
+ZnSetOrigin(ZnWInfo *wi,
+ ZnReal x_origin,
+ ZnReal y_origin)
{
int left, right, top, bottom, delta;
@@ -6490,7 +6594,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget.
}
break;
}
- SetOrigin(wi, new_x, wi->origin.y);
+ ZnSetOrigin(wi, new_x, wi->origin.y);
}
break;
}
@@ -6534,7 +6638,7 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget.
}
break;
}
- SetOrigin(wi, wi->origin.x, new_y);
+ ZnSetOrigin(wi, wi->origin.x, new_y);
}
break;
}
@@ -6783,7 +6887,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */
if (CONFIG_PROBE(SCROLL_REGION_SPEC) ||
CONFIG_PROBE(CONFINE_SPEC)) {
- SetOrigin(wi, wi->origin.x, wi->origin.y);
+ ZnSetOrigin(wi, wi->origin.x, wi->origin.y);
SET(wi->flags, ZN_UPDATE_SCROLLBARS);
}
@@ -6900,7 +7004,7 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */
}
if ((mask & CONFIG_SET_ORIGIN) || init) {
- SetOrigin(wi, wi->origin.x, wi->origin.y);
+ ZnSetOrigin(wi, wi->origin.x, wi->origin.y);
SET(wi->flags, ZN_UPDATE_SCROLLBARS);
}
@@ -7184,75 +7288,82 @@ TopEvent(ClientData client_data, /* Information about widget. */
}
static void
-Event(ClientData client_data, /* Information about widget. */
- XEvent *event) /* Information about event. */
+FinishSetup(ZnWInfo *wi)
{
- ZnWInfo *wi = (ZnWInfo *) client_data;
- XGCValues values;
- ZnBBox bbox;
+ XGCValues values;
+ Tk_Window top_level;
- /*printf("=============== DEBUT %s %d EVENT ==================\n",
- event->type == MapNotify ? "MAP":
- event->type == Expose? "EXPOSE" :
- event->type == ConfigureNotify ? "CONFIGURE" :
- event->type == VisibilityNotify ? "VISIBILITY" :
- event->type == DestroyNotify ? "DESTROY" :
- "??", event->type);*/
- if (event->type == MapNotify) {
- SET(wi->flags, ZN_CONFIGURE_EVENT);
- if (!wi->gc) {
- SET(wi->flags, ZN_REALIZED);
+ if (!wi->gc) {
+ SET(wi->flags, ZN_REALIZED);
+ top_level = wi->win;
+ while (!Tk_IsTopLevel(top_level)) {
+ top_level = Tk_Parent(top_level);
+ }
#ifdef GL
- InitRendering2(wi);
+ InitRendering2(wi, top_level);
#endif
- /*
- * Get the work GC and suppress GraphicExpose
- * and NoExpose events reception.
- */
- wi->gc = XCreateGC(wi->dpy, Tk_WindowId(wi->win), 0, NULL);
- values.graphics_exposures = False;
- XChangeGC(wi->dpy, wi->gc, GCGraphicsExposures, &values);
+ /*
+ * Get the work GC and suppress GraphicExpose
+ * and NoExpose events reception.
+ */
+ wi->gc = XCreateGC(wi->dpy, Tk_WindowId(wi->win), 0, NULL);
+ values.graphics_exposures = False;
+ XChangeGC(wi->dpy, wi->gc, GCGraphicsExposures, &values);
+ /*
+ * Set the real top window above us.
+ */
+ {
+ Window parent, root, *children=NULL;
+ int num_children, success;
+
+ success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent,
+ &children, &num_children);
+ if (!success || (root == parent)) {
+ wi->real_top = Tk_WindowId(top_level);
+ }
+ else {
+ wi->real_top = parent;
+ }
/*
- * Set the real top window above us.
+ * Needed under glx to suspend update with scissors after
+ * a move to synchronise the two buffers. Fix a refresh
+ * bug when the window is partially clipped by the display
+ * border. Can be usefull under Windows too.
*/
- {
- Window parent, root, *children=NULL;
- Tk_Window top_level;
- int num_children, success;
-
- top_level = wi->win;
- while (!Tk_IsTopLevel(top_level)) {
- top_level = Tk_Parent(top_level);
- }
- success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent,
- &children, &num_children);
- if (!success || (root == parent)) {
- wi->real_top = Tk_WindowId(top_level);
- }
- else {
- wi->real_top = parent;
- }
- /*
- * Needed under glx to suspend update with scissors after
- * a move to synchronise the two buffers. Fix a refresh
- * bug when the window is partially clipped by the display
- * border. Can be usefull under Windows too.
- */
- Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi);
- if (children && success) {
- XFree(children);
- }
+ Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi);
+ if (children && success) {
+ XFree(children);
}
}
+ }
+}
+
+static void
+Event(ClientData client_data, /* Information about widget. */
+ XEvent *event) /* Information about event. */
+{
+ ZnWInfo *wi = (ZnWInfo *) client_data;
+ ZnBBox bbox;
+
+ //printf("=============== DEBUT %s %d EVENT ==================\n",
+ // event->type == MapNotify ? "MAP":
+ // event->type == Expose? "EXPOSE" :
+ // event->type == ConfigureNotify ? "CONFIGURE" :
+ // event->type == VisibilityNotify ? "VISIBILITY" :
+ // event->type == DestroyNotify ? "DESTROY" :
+ // "??", event->type);
+ if (event->type == MapNotify) {
+ SET(wi->flags, ZN_CONFIGURE_EVENT);
+ FinishSetup(wi);
ZnNeedRedisplay(wi);
}
else if (event->type == Expose) {
ZnDim width, height;
SET(wi->flags, ZN_CONFIGURE_EVENT);
-
+ FinishSetup(wi);
bbox.orig.x = (((XExposeEvent*) event)->x);
bbox.orig.y = (((XExposeEvent*) event)->y);
width = ((XExposeEvent*) event)->width;
@@ -7268,9 +7379,9 @@ Event(ClientData client_data, /* Information about widget. */
bbox.corner.x = MIN(wi->width, bbox.orig.x + width);
bbox.corner.y = MIN(wi->height, bbox.orig.y + height);
- /*printf("expose %d %d %d %d\n",
- ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y,
- ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);*/
+ //printf("expose %d %d %d %d\n",
+ // ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y,
+ // ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);
/*
* Add the exposed area to the expose region and
* schedule an asynchronous redisplay of the window
@@ -7292,6 +7403,7 @@ Event(ClientData client_data, /* Information about widget. */
int int_width, int_height;
SET(wi->flags, ZN_CONFIGURE_EVENT);
+ FinishSetup(wi);
int_width = Tk_Width(wi->win);
int_height = Tk_Height(wi->win);
@@ -7311,7 +7423,7 @@ Event(ClientData client_data, /* Information about widget. */
* it's confined and the scroll region is smaller than the
* window.
*/
- SetOrigin(wi, wi->origin.x, wi->origin.y);
+ ZnSetOrigin(wi, wi->origin.x, wi->origin.y);
ZnDamage(wi, &bbox);
ZnITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG);
@@ -7328,6 +7440,14 @@ Event(ClientData client_data, /* Information about widget. */
int_width, int_height,
DefaultDepthOfScreen(wi->screen));
}
+#if defined(MAC_OSX_TK)
+ else {
+ ZnGLContextEntry *ce = ZnGLMakeCurrent(wi->dpy, wi);
+ UpdateBufferRect(ce, wi->win);
+ aglUpdateContext(ce->context);
+ }
+#endif
+
}
else {
/*
@@ -8237,9 +8357,12 @@ Destroy(ZnWInfo *wi)
}
}
}
-#ifdef _WIN32
+#if defined(_WIN32)
ZnGLReleaseContext(ce);
wglDeleteContext(ce->context);
+#elif defined(MAC_OSX_TK)
+ aglDestroyPixelFormat(ce->pix_fmt);
+ aglDestroyContext(ce->context);
#else
glXDestroyContext(ce->dpy, ce->context);
/*
@@ -8447,7 +8570,7 @@ Repair(ZnWInfo *wi)
}
#endif
- /*printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));*/
+ //printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));
ce = ZnGLMakeCurrent(wi->dpy, wi);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);