Skip to content

Commit 4018c5e

Browse files
committed
FEAT: initial implementation of OpenGL widget
Nothing special yet, just displays hard-coded triangle with random background on redraw. Minimal example: ``` view make gob! [size: 400x400 widget: 'opengl] ```
1 parent 9e2c7be commit 4018c5e

File tree

3 files changed

+155
-14
lines changed

3 files changed

+155
-14
lines changed

src/boot/window.r

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ words: [
3131
slider
3232
date-time
3333
group-box
34+
opengl
3435

3536
;- gui-metric
3637
border-fixed

src/os/win32/host-event.c

+109
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
#include <zmouse.h>
4848
#include <math.h> //for floor()
4949

50+
//OpenGL
51+
#pragma comment(lib, "opengl32")
52+
#pragma comment(lib, "glu32")
53+
#include <gl/gl.h>
54+
#include <gl/glu.h>
55+
5056
//-- Not currently used:
5157
//#include <windowsx.h>
5258
//#include <mmsystem.h>
@@ -495,3 +501,106 @@ static REBINT Check_Modifiers(REBINT flags)
495501
}
496502
return DefWindowProc(hwnd, msg, wParam, xy);
497503
}
504+
505+
506+
/***********************************************************************
507+
**
508+
*/ LRESULT CALLBACK REBOL_OpenGL_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
509+
/*
510+
** An OpenGL message handler.
511+
**
512+
***********************************************************************/
513+
{
514+
REBGOB *gob;
515+
REBCNT flags = 0;
516+
HDC hdc;
517+
HGLRC hglrc;
518+
PIXELFORMATDESCRIPTOR pfd;
519+
PAINTSTRUCT ps;
520+
521+
522+
#ifdef __LLP64__
523+
gob = (REBGOB *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
524+
#else
525+
gob = (REBGOB *)GetWindowLong(hwnd, GWL_USERDATA);
526+
#endif
527+
528+
//if(msg != WM_PAINT)
529+
// printf("OpenGL_Proc - msg: %0X wParam: %0X lParam: %0X gob: %0Xh\n", msg, wParam, lParam, gob);
530+
531+
// Handle message:
532+
switch (msg)
533+
{
534+
case WM_PAINT:
535+
hdc = BeginPaint(hwnd, &ps);
536+
//TODO: retrive context from gob's handle
537+
//hglrc = wglGetCurrentContext();
538+
//wglMakeCurrent(hdc, hglrc);
539+
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
540+
glBegin(GL_TRIANGLES);
541+
glColor3ub(255, 0, 0); glVertex2d(-0.75, -0.75);
542+
glColor3ub(0, 255, 0); glVertex2d(0.0, 0.75);
543+
glColor3ub(0, 0, 255); glVertex2d(0.75, -0.75);
544+
glEnd();
545+
glFlush();
546+
547+
wglSwapBuffers(hdc);
548+
// wglMakeCurrent(hdc, 0);
549+
EndPaint(hwnd, &ps);
550+
return FALSE;
551+
case WM_ERASEBKGND:
552+
// for testing purposes, set random background so far...
553+
glClearColor(((float)rand()/(float)(RAND_MAX))*1.0, 0.0, 0.0, 0.0);
554+
555+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
556+
break;
557+
case WM_SIZE:
558+
glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));
559+
break;
560+
case WM_CREATE:
561+
hdc = GetDC(hwnd);
562+
ZeroMemory(&pfd, sizeof(pfd));
563+
PIXELFORMATDESCRIPTOR pfd = {
564+
sizeof(PIXELFORMATDESCRIPTOR),
565+
1,
566+
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
567+
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
568+
32, // Colordepth of the framebuffer.
569+
0, 0, 0, 0, 0, 0,
570+
0,
571+
0,
572+
0,
573+
0, 0, 0, 0,
574+
24, // Number of bits for the depthbuffer
575+
8, // Number of bits for the stencilbuffer
576+
0, // Number of Aux buffers in the framebuffer.
577+
PFD_MAIN_PLANE,
578+
0,
579+
0, 0, 0
580+
};
581+
int pf = ChoosePixelFormat(hdc, &pfd);
582+
if (!pf) {
583+
RL_Print("Could not find a pixel format.. OpenGL cannot create its context.\n");
584+
return FALSE;
585+
}
586+
SetPixelFormat(hdc, pf, &pfd);
587+
hglrc = wglCreateContext(hdc);
588+
if (hglrc) {
589+
wglMakeCurrent(hdc, hglrc);
590+
}
591+
else {
592+
RL_Print("Failed to create OpenGL context!\n");
593+
return FALSE;
594+
}
595+
RL_Print("OPENGL CONTEXT CREATED!\n");
596+
RL_Print("Version %s\n", glGetString(GL_VERSION));
597+
return FALSE;
598+
599+
case WM_DESTROY:
600+
hglrc = wglGetCurrentContext();
601+
wglDeleteContext(hglrc);
602+
return FALSE;
603+
}
604+
605+
return REBOL_Window_Proc(hwnd, msg, wParam, lParam);
606+
}

src/os/win32/host-window.c

+45-14
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ typedef HRESULT(WINAPI * GETDPIFORMONITOR_T)(HMONITOR, MONITOR_DPI_TYPE, UINT*,
101101
extern HINSTANCE App_Instance; // Set by winmain function
102102
extern void Host_Crash(char *reason);
103103
extern LRESULT CALLBACK REBOL_Window_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
104+
extern LRESULT CALLBACK REBOL_OpenGL_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
104105

105106
//***** Locals *****//
106107

@@ -112,6 +113,7 @@ static struct gob_window *Gob_Windows;
112113
static REBOOL DPI_Aware = FALSE;
113114
static REBOOL Custom_Cursor = FALSE;
114115
static HFONT Default_Font = NULL;
116+
static REBOOL Windows8_And_Newer = FALSE;
115117

116118
static u32* window_ext_words;
117119

@@ -311,7 +313,7 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
311313

312314
wc.hIcon = LoadIcon(App_Instance, MAKEINTRESOURCE(101));
313315
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
314-
wc.hbrBackground = NULL;
316+
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
315317
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
316318

317319
wc.cbClsExtra = 0;
@@ -328,6 +330,10 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
328330

329331
if (!RegisterClassEx(&wc)) Host_Crash("Cannot register window");
330332

333+
wc.lpfnWndProc = REBOL_OpenGL_Proc;
334+
wc.lpszClassName = TXT("RebOpenGL");
335+
if (!RegisterClassEx(&wc)) puts("Failed to register OpenGL class");
336+
331337
Make_Subclass(Class_Name_Button, TEXT("BUTTON"), NULL, TRUE);
332338

333339
Registered = TRUE;
@@ -543,7 +549,10 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
543549
REBOOL changed;
544550
compositor = GOB_COMPOSITOR(gob);
545551
changed = OS_Resize_Window_Buffer(compositor, gob);
546-
if (redraw) OS_Compose_Gob(compositor, gob, gob, FALSE); // what if not actually resized?
552+
if (redraw) {
553+
OS_Compose_Gob(compositor, gob, gob, FALSE); // what if not actually resized?
554+
OS_Blit_Window(compositor);
555+
}
547556
return changed;
548557
}
549558

@@ -635,7 +644,7 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
635644
//render and blit the GOB
636645
compositor = GOB_COMPOSITOR(wingob);
637646
OS_Compose_Gob(compositor, wingob, gob, FALSE);
638-
OS_Blit_Window(compositor);
647+
//OS_Blit_Window(compositor); //@@ When used, the content overwrites native widgets which are than invisible:/
639648
}
640649

641650

@@ -709,6 +718,10 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
709718
}
710719
return 0;
711720
}
721+
// Is it a native widget?
722+
else if (GOBT_WIDGET == GOB_TYPE(gob)) {
723+
RedrawWindow((HWND)VAL_HANDLE(GOB_WIDGET_HANDLE(gob)), NULL, NULL, RDW_INVALIDATE | RDW_ERASE);
724+
}
712725
// Is it a window gob that needs to be closed?
713726
else if (!GOB_PARENT(gob) && GET_GOB_FLAG(gob, GOBF_WINDOW)) {
714727
OS_Close_Window(gob);
@@ -819,6 +832,10 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
819832
class = TXT("BUTTON");
820833
style |= BS_GROUPBOX;
821834
break;
835+
case W_WINDOW_OPENGL:
836+
class = TXT("RebOpenGL");
837+
style |= CS_OWNDC;
838+
break;
822839
default:
823840
//RL_Print("unknown widget name");
824841
return NULL;
@@ -1339,18 +1356,32 @@ static REBCNT Get_Widget_Text(HWND widget, REBVAL *text);
13391356
Cursor = LoadCursor(NULL, IDC_ARROW);
13401357
Init_DPI_Awareness();
13411358

1359+
// Get information about system version
1360+
// https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_osversioninfoa
1361+
OSVERSIONINFO vi;
1362+
GetVersionEx(&vi);
13421363

1343-
INITCOMMONCONTROLSEX InitCtrlEx;
1344-
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
1345-
InitCtrlEx.dwICC = ICC_STANDARD_CLASSES
1346-
| ICC_LINK_CLASS
1347-
| ICC_UPDOWN_CLASS
1348-
| ICC_LISTVIEW_CLASSES
1349-
| ICC_PROGRESS_CLASS
1350-
| ICC_BAR_CLASSES
1351-
| ICC_DATE_CLASSES;
1352-
if (!InitCommonControlsEx(&InitCtrlEx)) {
1353-
RL_Print("Could not initialize common controls! (%u)\n", GetLastError());
1364+
if (
1365+
vi.dwMajorVersion >= 10 // Windows10 and newer
1366+
| (vi.dwMajorVersion >= 6 && vi.dwMinorVersion >= 2) //Win8
1367+
) {
1368+
Windows8_And_Newer = TRUE;
1369+
}
1370+
1371+
if (!(vi.dwMajorVersion == 5 && vi.dwMinorVersion < 1)) {
1372+
// Enable visual styles (not for Win2000)
1373+
INITCOMMONCONTROLSEX InitCtrlEx;
1374+
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
1375+
InitCtrlEx.dwICC = ICC_STANDARD_CLASSES
1376+
| ICC_LINK_CLASS
1377+
| ICC_UPDOWN_CLASS
1378+
| ICC_LISTVIEW_CLASSES
1379+
| ICC_PROGRESS_CLASS
1380+
| ICC_BAR_CLASSES
1381+
| ICC_DATE_CLASSES;
1382+
if (!InitCommonControlsEx(&InitCtrlEx)) {
1383+
RL_Print("Could not initialize common controls!\n");
1384+
}
13541385
}
13551386
}
13561387

0 commit comments

Comments
 (0)