From edccff5a624c65436a0f3278507ca2efd3458c77 Mon Sep 17 00:00:00 2001 From: Jafar Al-Gharaibeh Date: Mon, 29 Apr 2024 00:03:21 -0500 Subject: [PATCH] runtime: add support for opengl2d to Windows Signed-off-by: Jafar Al-Gharaibeh --- README.md | 5 +- src/h/opengl.h | 10 +- src/h/rproto.h | 1 + src/runtime/fsys.r | 28 +++--- src/runtime/rdebug.r | 2 +- src/runtime/rmswin.ri | 204 +++++++++++++++++++++++++++++++-------- src/runtime/ropengl.ri | 2 +- src/runtime/ropengl2d.ri | 58 ++++++++--- src/runtime/rxwin.ri | 24 ++++- 9 files changed, 255 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 0730636ed..2c4ade91c 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,8 @@ pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86 - Install the optional libraries for a full build (Unicon will build without them but some features will be absent). ``` -pacman -S mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-libpng mingw-w64-ucrt-x86_64-libjpeg-turbo +pacman -S mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-libpng +pacman -S mingw-w64-ucrt-x86_64-libjpeg-turbo mingw-w64-ucrt-x86_64-freetype ``` - Clone the Unicon repository: @@ -149,7 +150,7 @@ git clone --config core.autocrlf=input https://github.com/uniconproject/unicon - Configure Unicon: ``` -./configure --build=x86_64-w64-mingw32 +./configure --build=x86_64-w64-mingw32 CPPFLAGS=-I/ucrt64/include/freetype2 ``` The option `x86_64-w64-mingw32` ensures the build is 64-bit. After the script finishes do: ``` diff --git a/src/h/opengl.h b/src/h/opengl.h index 5c5ff4872..2d595c977 100644 --- a/src/h/opengl.h +++ b/src/h/opengl.h @@ -5,8 +5,10 @@ //#define GL2D_DRAWARRAYS 1 /* Punt this off as a TODO item */ +#define GL2D_DEBUG + #ifdef GL2D_DEBUG -#define glprintf(s, ...) printf(stderr,s, ##__VA_ARGS__) +#define glprintf(s, ...) fprintf(stderr, "%s:%s:%d: " s, __FILE__, __func__, __LINE__, ##__VA_ARGS__) #else /* GL2D_DEBUG */ #define glprintf(s, ...) #endif /* GL2D_DEBUG */ @@ -111,7 +113,6 @@ #define GL2D_DRAWOP_COPY GL_COPY #define GL2D_DRAWOP_REVERSE GL_XOR - /* * Structures */ @@ -119,7 +120,8 @@ /* * For a linked list color structure */ -typedef struct color { +typedef struct color +{ char name[6+MAXCOLORNAME]; unsigned short r, g, b, a; /* for referencing a mutable color (negative) */ @@ -128,7 +130,7 @@ typedef struct color { unsigned long c; /* X11 color handle */ #endif /* XWindows */ struct color *prev, *next; - } *clrp; +} *clrp; /* * Object for storing font characters (uses textures) diff --git a/src/h/rproto.h b/src/h/rproto.h index 0629e0754..d9c9cb0c2 100644 --- a/src/h/rproto.h +++ b/src/h/rproto.h @@ -941,6 +941,7 @@ int checkOpenConsole( FILE *w, char *s ); */ wcp gl_alc_context(wbp w); wdp gl_alc_display(char *s); + wdp gl_alc_display_font(wdp wd); wsp gl_alc_winstate(); void gl_free_context(wcp wc); void gl_free_display(wdp wd); diff --git a/src/runtime/fsys.r b/src/runtime/fsys.r index 82357e776..b6592641c 100644 --- a/src/runtime/fsys.r +++ b/src/runtime/fsys.r @@ -475,31 +475,25 @@ Deliberate Syntax Error XInitThreads(); #endif /* XWindows */ #ifdef GraphicsGL - /* - * For now, having FreeType is a requirement for the OpenGL - * 2D and 2D/3D implementation - */ -#if HAVE_LIBFREETYPE /* for enabling OpenGL 2D implementation in a convenient way */ - if (!getenv("UNICONGL2D")) + if (getenv("UNICONGL2D")) { + /* + * FreeType is a requirement for OpenGL 2D + */ +#if !HAVE_LIBFREETYPE + set_errortext(1045); + fail; #endif /* HAVE_LIBFREETYPE */ + if (status & Fs_Window) { + status |= Fs_WinGL2D; + } + } #endif /* GraphicsGL */ continue; #else /* Graphics */ set_errortext(148); fail; #endif /* Graphics */ -#ifdef GraphicsGL - /* OpenGL 2D implementation */ - if (status & Fs_Window) { - status |= Fs_WinGL2D; - continue; - } -#else - /* Does it need a specific code? */ - set_errortext(1045); - fail; -#endif /* GraphicsGL */ case 'l': case 'L': #ifdef PosixFns diff --git a/src/runtime/rdebug.r b/src/runtime/rdebug.r index 06f1ea38c..28ff0e367 100644 --- a/src/runtime/rdebug.r +++ b/src/runtime/rdebug.r @@ -1040,7 +1040,7 @@ oneop: fprintf(stderr,"; coexpression_%ld failed to thread_%ld\n", (long)ccp->id, (long)ncp->id); else -#endif +#endif /* Concurrent */ fprintf(stderr,"; co-expression_%ld failed to co-expression_%ld\n", (long)ccp->id, (long)ncp->id); fflush(stderr); diff --git a/src/runtime/rmswin.ri b/src/runtime/rmswin.ri index 7b8eb2069..4b1d1c4bd 100644 --- a/src/runtime/rmswin.ri +++ b/src/runtime/rmswin.ri @@ -217,12 +217,12 @@ char *lookcmdname(char *buf, char *s) /* * wopen - * If it returns NULL, per fsys.r, wopen() should set err_idx to one of: + * If it returns NULL, per fsys.r, wopen() should set err_index to one of: * >= 0: the index of an offending attribute value * -1 : ordinary failure * -2 : out of memory */ -FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int is_3d, int is_gl) +FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int is_3d, int is_gl) { wbp w; wsp ws; @@ -248,33 +248,118 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int i } tlp = lp; + /* * Allocate a binding, a window state, and a context. * If anything goes wrong, a free_binding() call clears it all out. */ - if (((w = alc_wbinding()) == NULL) || - ((ws = w->window = alc_winstate()) == NULL) || - ((ws->display = alc_display(NULL)) == NULL) || - ((wc = w->context = alc_context(w)) == NULL)) { - if (w) free_binding(w); - *err_idx = -2; + if ((w = alc_wbinding()) == NULL) { + *err_index = -2; + set_errortext(145); + return NULL; + } + +#ifdef GraphicsGL + if (is_gl) { + if ((ws = w->window = gl_alc_winstate()) == NULL) { + *err_index = -2; + free_binding(w); + set_errortext(145); /* maybe out of memory */ + return NULL; + } + if ((ws->display = gl_alc_display(NULL)) == NULL) { + *err_index = -1; + free_binding(w); + set_errortext(145); + return NULL; + } + if ((gl_alc_display_font(ws->display)) == NULL) { + if (!is_3d) { + *err_index = -1; + free_binding(w); + set_errortext(145); + return NULL; + } + } + } + else +#endif /* GraphicsGL */ + { + if ((ws = w->window = alc_winstate()) == NULL) { + *err_index = -2; + free_binding(w); + set_errortext(145); + return NULL; + } + + if ((ws->display = alc_display(NULL)) == NULL) { + *err_index = -1; + free_binding(w); + set_errortext(145); return NULL; } + } + ws->children=NULL; + ws->parent = NULL; + ws->width = ws->height = 0; ws->listp.dword = D_List; BlkLoc(ws->listp) = (union block *) tlp; - ws->width = ws->height = 0; -#ifdef Graphics3D - ws->is_3D = wc->rendermode = is_3d; - if (is_3d) { - /* create an empty list for list of function calls */ - if (create_display_list(w, 40000) == Failed) { - *err_idx = -2; + #ifdef GraphicsGL + ws->is_3D = is_3d; + #endif /* GraphicsGL */ + + /* + * some attributes of the display and window are used in the context + */ + +#ifdef GraphicsGL + if (is_gl) { + if ((wc = w->context = gl_alc_context(w)) == NULL) { + *err_index = -2; + free_binding(w); + set_errortext(145); return NULL; } } -#endif /* Graphics3D */ + else +#endif /* GraphicsGL */ + if ((wc = w->context = alc_context(w)) == NULL) { + *err_index = -2; + free_binding(w); + return NULL; + } + +#ifdef GraphicsGL + if (is_gl) { + wc->rendermode = is_3d; + + /* Allocate display lists */ + if (is_3d) { + if (create_display_list(w, 40000) == Failed) { + *err_index = -2; + return NULL; + } + } + if (create_display_list2d(w, 40000) == Failed) { + *err_index = -2; + return NULL; + } + + /* + * Need to determine a way to initialize the default context for a + * window without adding items to the display list. + */ + if (!ws->initAttrs) + ws->initAttrs = 1; + else { + glprintf("gl_wopen(): need a mutex lock\n"); + return NULL; + } + } +#endif /* GraphicsGL */ + /* * process the passed in attributes - by calling wattrib @@ -282,27 +367,40 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int i for(i = 0; i < n; i++) switch (wattrib(w, StrLoc(attr[i]), StrLen(attr[i]), &attrrslt, answer)) { + case RunError: + *err_index = i; + return NULL; case Failed: wclose(w); /* suspicious; didn't get it opened OK */ set_errortext(145); - *err_idx = -1; - return NULL; - case RunError: - *err_idx = i; + *err_index = -1; return NULL; } /* * set the title, defaulting to the "filename" supplied to open() */ - if (ws->windowlabel == NULL) ws->windowlabel = salloc(name); - if (ws->iconlabel == NULL) ws->iconlabel = salloc(name); + if (ws->windowlabel == NULL) { + ws->windowlabel = salloc(name); + if (ws->windowlabel == NULL) { /* out of memory */ + *err_index = -2; + set_errortext(145); + return NULL; + } + } + + if (ws->iconlabel == NULL) { + ws->iconlabel = salloc(name); + if (ws->iconlabel == NULL) { /* out of memory */ + *err_index = -2; + set_errortext(145); + return NULL; + } + } if (ws->posx < 0) ws->posx = 0; if (ws->posy < 0) ws->posy = 0; ws->no = 0; - ws->children = NULL; - ws->parent = NULL; /* * create the window @@ -342,18 +440,23 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int i scp[1].type = CLR_SHARED; strcpy(scp[1].name, "white"); } - oldfont = SelectObject(hdc, wc->font->font); - GetTextMetrics(hdc, &metrics); - wc->font->charwidth = dc_maxcharwidth(hdc); - SelectObject(hdc, oldfont); - ReleaseDC(ws->iconwin, hdc); - wc->font->ascent = metrics.tmAscent; - wc->font->descent = metrics.tmDescent; - /* wc->font->charwidth = metrics.tmMaxCharWidth; buggy */ - wc->font->height = metrics.tmHeight; - wc->leading = metrics.tmHeight; + + if (wc->font) { + oldfont = SelectObject(hdc, wc->font->font); + GetTextMetrics(hdc, &metrics); + wc->font->charwidth = dc_maxcharwidth(hdc); + SelectObject(hdc, oldfont); + ReleaseDC(ws->iconwin, hdc); + wc->font->ascent = metrics.tmAscent; + wc->font->descent = metrics.tmDescent; + /* wc->font->charwidth = metrics.tmMaxCharWidth; buggy */ + wc->font->height = metrics.tmHeight; + wc->leading = metrics.tmHeight; + ws->y = ASCENT(w); + } + else + ws->y = 7; ws->x = 0; - ws->y = ASCENT(w); ws->y += w->context->dy; ws->x += w->context->dx; /* @@ -375,11 +478,11 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int i } if (alc_rgb(w, wc->fg) == Failed) { - *err_idx = -1; /* review */ + *err_index = -1; /* review */ return 0; } if (alc_rgb(w, wc->bg) == Failed) { - *err_idx = -1; /* review */ + *err_index = -1; /* review */ return 0; } ws->pixwidth = ws->width; @@ -452,7 +555,7 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx, int i free((pointer)imd->data); imd->width = 0; if (r < 0) { - *err_idx = -1; /* review. when does strimage fail? */ + *err_index = -1; /* review. when does strimage fail? */ return 0; } } @@ -1159,12 +1262,37 @@ int pollevent() wbp w; MSG m; extern jmp_buf mark_sj; +#ifdef GraphicsGL + wbp wb; + static int gpx_poll = FLUSH_POLL_INTERVAL; +#endif /* GraphicsGL */ #ifdef Concurrent int isbusy; MUTEX_TRYLOCKID(MTX_POLLEVENT, isbusy); if (isbusy) return POLL_INTERVAL; #endif /* Concurrent */ +#ifdef GraphicsGL + if (gpx_poll) gpx_poll--; + if (!gpx_poll) { + for (wb = wbndngs; wb; wb=wb->next) { + wsp ws = wb->window; + if (ws->buffermode == UGL_IMMEDIATE) { + if (ws->redraw_flag && !ws->busy_flag) { + ws->busy_flag = 1; + + MakeCurrent(wb); + glFlush(); + + ws->redraw_flag = 0; + ws->busy_flag = 0; + } + } + } + gpx_poll = FLUSH_POLL_INTERVAL; + } +#endif /* GraphicsGL */ + /* some while PeekMessage loops here, maybe one per window ? */ while (PeekMessage(&m, NULL, 0, 0, PM_NOREMOVE)) { if (GetMessage(&m, NULL, 0, 0) == 0) longjmp(mark_sj, -1); diff --git a/src/runtime/ropengl.ri b/src/runtime/ropengl.ri index 15453c17d..b5fbe0cd2 100644 --- a/src/runtime/ropengl.ri +++ b/src/runtime/ropengl.ri @@ -2957,7 +2957,7 @@ int lookup_texture_byname(wbp w, char *name, int len, int ttype, int curtex) StrLen(wt->d) = len; wt->w = w; - glBindTexture(GL_TEXTURE_2D, wt->texName); + UGLBindTexture(GL_TEXTURE_2D, wt->texName); if (ttype == 3) i = imagestr(w, name); diff --git a/src/runtime/ropengl2d.ri b/src/runtime/ropengl2d.ri index 9fa5d2e9f..7b97820b1 100644 --- a/src/runtime/ropengl2d.ri +++ b/src/runtime/ropengl2d.ri @@ -1429,6 +1429,16 @@ int init_2dcontext(wcp wc) glprintf("fonts not allocated\n"); wc->font = NULL; wc->leading = 0; + wc->font = (wfp)alloc(sizeof (struct _wfont)); + wc->font->name = salloc("fixed"); + wc->font->font = CreateFont(16,0,0,0,FW_NORMAL,0,0,0, + ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET), + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, + NULL); + + wc->font->charwidth = 8; /* looks like a bug */ + wc->leading = 16; } /* drawing */ @@ -1486,15 +1496,20 @@ int copy_2dcontext(wcp wcdest, wcp wcsrc) wcdest->leading = wcsrc->leading; } - if (wcdest->patternname) { - if (strcmp(wcdest->patternname,wcsrc->patternname)) { - free(wcdest->patternname); + if (wcsrc->patternname != NULL) + if (wcdest->patternname) { + if (strcmp(wcdest->patternname,wcsrc->patternname)) { + free(wcdest->patternname); + wcdest->patternname = strdup(wcsrc->patternname); + } + } + else { wcdest->patternname = strdup(wcsrc->patternname); } - } - else { - wcdest->patternname = strdup(wcsrc->patternname); - } + else if (wcdest->patternname != NULL) { + free(wcdest->patternname); + wcdest->patternname = NULL; + } wcdest->fillstyle = wcsrc->fillstyle; wcdest->linestyle = wcsrc->linestyle; @@ -3167,9 +3182,15 @@ int setpattern2d(wbp w, struct b_record *rp) } } else { - update = 1; - s = wcr->patternname; - slen = strlen(wcr->patternname); + update = 1; + /* "black" is default pattern */ + if (wcr->patternname == NULL) { + return Failed; + wcr->patternname = strdup("black"); + if (!wcr->patternname) return RunError; + } + s = wcr->patternname; + slen = strlen(wcr->patternname); } if (update) { @@ -6683,7 +6704,9 @@ static wfp loadfont(wdp wd, char *s, int len) wf->size = size; /* in pixels */ wf->ascent = FT_ASCENT(wf->face); wf->descent = FT_DESCENT(wf->face); + #ifdef XWindows wf->maxwidth = FT_FWIDTH(wf->face); + #endif /* XWindows */ wf->height = FT_FHEIGHT(wf->face); /* @@ -7515,9 +7538,19 @@ wdp gl_alc_display(char *s) wd->maxTexIds = 256; wd->numTexIds = 0; wd->texIds = (unsigned int *)malloc(wd->maxTexIds*sizeof(unsigned int)); - if (!wd->texIds) return NULL; + if (!wd->texIds) { + free(wd); + return NULL; + } } + return wd; + } +/* + * allocate font for a display + */ +wdp gl_alc_display_font(wdp wd) +{ if (!wd->glfonts) { wd->numFonts = 1; wd->glfonts = loadfont(wd,DEFAULTFONTNAME,strlen(DEFAULTFONTNAME)); @@ -7527,7 +7560,8 @@ wdp gl_alc_display(char *s) } } return wd; - } +} + diff --git a/src/runtime/rxwin.ri b/src/runtime/rxwin.ri index 271cac903..ce3699c22 100644 --- a/src/runtime/rxwin.ri +++ b/src/runtime/rxwin.ri @@ -1194,7 +1194,6 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int tended struct b_list *tlp; tended struct descrip attrrslt; - tlp = lp; for(i=0;i8) && @@ -1205,15 +1204,25 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int } } + tlp = lp; + + /* + * Allocate a binding, a window state, and a context. + * If anything goes wrong, a free_binding() call clears it all out. + */ + if ((w = alc_wbinding()) == NULL) { *err_index = -2; + set_errortext(145); return NULL; } + #ifdef GraphicsGL if (is_gl) { if ((ws = w->window = gl_alc_winstate()) == NULL) { *err_index = -2; free_binding(w); + set_errortext(145); return NULL; } if ((ws->display = gl_alc_display(display)) == NULL) { @@ -1229,10 +1238,11 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int if ((ws = w->window = alc_winstate()) == NULL) { *err_index = -2; free_binding(w); + set_errortext(145); return NULL; } - if ((w->window->display = alc_display(display)) == NULL) { + if ((ws->display = alc_display(display)) == NULL) { *err_index = -1; free_binding(w); set_errortext(145); /* maybe out of memory, probably bad DISPLAY var. */ @@ -1241,13 +1251,13 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int ws->vis = DefaultVisual(ws->display->display, ws->display->screen); } - ws->children=NULL; ws->parent = NULL; - + ws->width = ws->height = 0; ws->listp.dword = D_List; BlkLoc(ws->listp) = (union block *)tlp; + /* * some attributes of the display and window are used in the context */ @@ -1338,10 +1348,16 @@ FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_index, int } } } + + /* + * set the title, defaulting to the "filename" supplied to open() + */ + if (ws->windowlabel == NULL) { ws->windowlabel = salloc(name); if (ws->windowlabel == NULL) { /* out of memory */ *err_index = -2; + set_errortext(145); return NULL; } }