aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/c_src/wxe_gl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wx/c_src/wxe_gl.cpp')
-rw-r--r--lib/wx/c_src/wxe_gl.cpp321
1 files changed, 321 insertions, 0 deletions
diff --git a/lib/wx/c_src/wxe_gl.cpp b/lib/wx/c_src/wxe_gl.cpp
new file mode 100644
index 0000000000..63dd68fa5e
--- /dev/null
+++ b/lib/wx/c_src/wxe_gl.cpp
@@ -0,0 +1,321 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2008-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "wxe_impl.h"
+
+#include "wxe_gl.h"
+
+#define WX_DEF_EXTS
+#include "gen/gl_fdefs.h"
+#include "gen/gl_finit.h"
+#include "gen/glu_finit.h"
+
+/* ****************************************************************************
+ * Opengl context management *
+ * ****************************************************************************/
+int gl_initiated = FALSE;
+
+ErlDrvTermData gl_active = 0;
+wxeGLC glc;
+
+void setActiveGL(ErlDrvTermData caller, wxGLCanvas *canvas)
+{
+ if(gl_initiated == FALSE) {
+ initOpenGL();
+ init_tess();
+ gl_initiated = TRUE;
+ }
+ gl_active = caller;
+ glc[caller] = canvas;
+}
+
+void deleteActiveGL(wxGLCanvas *canvas)
+{
+ gl_active = 0;
+ wxeGLC::iterator it;
+ for(it = glc.begin(); it != glc.end(); ++it) {
+ if(it->second == canvas) {
+ it->second = (wxGLCanvas *) 0;
+ }
+ }
+}
+
+/* ****************************************************************************
+ * OPENGL INITIALIZATION
+ *****************************************************************************/
+
+#ifdef _WIN32
+void * dlsym(HMODULE Lib, const char *func) {
+ void * funcp;
+ if((funcp = (void *) GetProcAddress(Lib, func)))
+ return funcp;
+ else
+ return (void *) wglGetProcAddress(func);
+}
+#endif
+
+int initOpenGL()
+{
+#ifdef _MACOSX
+ char * DLName = "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib";
+ void * LIBhandle = dlopen(DLName, RTLD_LAZY);
+#elif defined(_WIN32)
+ WCHAR * DLName = wxT("opengl32.dll");
+ HMODULE LIBhandle = LoadLibrary(DLName);
+#else
+ char * DLName = (char *) "libGL.so";
+ void * LIBhandle = dlopen(DLName, RTLD_LAZY);
+#endif
+ // fprintf(stderr, "Loading GL: %s\r\n", (const char*)DLName);
+ void * func = NULL;
+ int i;
+
+ if(LIBhandle) {
+ for(i=0; gl_fns[i].name != NULL; i++) {
+ if((func = dlsym(LIBhandle, gl_fns[i].name))) {
+ * (void **) (gl_fns[i].func) = func;
+ // fprintf(stderr, "GL LOADED %s \r\n", gl_fns[i].name);
+ } else {
+ if(gl_fns[i].alt != NULL) {
+ if((func = dlsym(LIBhandle, gl_fns[i].alt))) {
+ * (void **) (gl_fns[i].func) = func;
+ // fprintf(stderr, "GL LOADED %s \r\n", gl_fns[i].alt);
+ } else {
+ * (void **) (gl_fns[i].func) = (void *) &gl_error;
+ // fprintf(stderr, "GL Skipped %s and %s \r\n", gl_fns[i].name, gl_fns[i].alt);
+ };
+ } else {
+ * (void **) (gl_fns[i].func) = (void *) &gl_error;
+ // fprintf(stderr, "GL Skipped %s \r\n", gl_fns[i].name);
+ }
+ }
+ }
+#ifdef _WIN32
+ FreeLibrary(LIBhandle);
+#else
+ dlclose(LIBhandle);
+#endif
+ // fprintf(stderr, "OPENGL library is loaded\r\n");
+ } else {
+ wxString msg;
+ msg.Printf(wxT("Could NOT load OpenGL library: "));
+#ifdef _WIN32
+ msg += DLName;
+#else
+ msg += wxString::FromAscii((char *)DLName);
+#endif
+ send_msg("error", &msg);
+ };
+
+#ifdef _MACOSX
+ DLName = "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib";
+ LIBhandle = dlopen(DLName, RTLD_LAZY);
+#elif defined(_WIN32)
+ DLName = wxT("glu32.dll");
+ LIBhandle = LoadLibrary(DLName);
+#else
+ DLName = (char *) "libGLU.so";
+ LIBhandle = dlopen(DLName, RTLD_LAZY);
+#endif
+ // fprintf(stderr, "Loading GL: %s\r\n", (const char*)DLName);
+ func = NULL;
+
+ if(LIBhandle) {
+ for(i=0; glu_fns[i].name != NULL; i++) {
+ if((func = dlsym(LIBhandle, glu_fns[i].name))) {
+ * (void **) (glu_fns[i].func) = func;
+ } else {
+ if(glu_fns[i].alt != NULL) {
+ if((func = dlsym(LIBhandle, glu_fns[i].alt))) {
+ * (void **) (glu_fns[i].func) = func;
+ } else {
+ * (void **) (glu_fns[i].func) = (void *) &gl_error;
+ // fprintf(stderr, "GLU Skipped %s\r\n", glu_fns[i].alt);
+ };
+ } else {
+ * (void **) (glu_fns[i].func) = (void *) &gl_error;
+ // fprintf(stderr, "GLU Skipped %s\r\n", glu_fns[i].name);
+ }
+ }
+ }
+#ifdef _WIN32
+ FreeLibrary(LIBhandle);
+#else
+ dlclose(LIBhandle);
+#endif
+ // fprintf(stderr, "GLU library is loaded\r\n");
+ } else {
+ wxString msg;
+ msg.Printf(wxT("Could NOT load OpenGL GLU library: "));
+#ifdef _WIN32
+ msg += DLName;
+#else
+ msg += wxString::FromAscii((char *)DLName);
+#endif
+ send_msg("error", &msg);
+ };
+ return 0;
+}
+
+void gl_error() {
+ int AP = 0; ErlDrvTermData rt[8];
+ rt[AP++] = ERL_DRV_ATOM; rt[AP++] = driver_mk_atom((char *)"_wxe_error_");
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) gl_error_op;
+ rt[AP++] = ERL_DRV_ATOM; rt[AP++] = driver_mk_atom((char *)"undef");
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 3;
+ driver_send_term(WXE_DRV_PORT,gl_active,rt,AP);
+}
+
+/* *******************************************************************************
+ * GLU Tesselation special
+ * ******************************************************************************/
+
+static GLUtesselator* tess;
+static GLdouble* tess_coords;
+static GLdouble* tess_alloc_vertex;
+static int* tess_vertices;
+
+void CALLBACK
+wxe_ogla_vertex(GLdouble* coords)
+{
+ /* fprintf(stderr, "%d\r\n", (int) (coords - tess_coords) / 3); */
+
+ *tess_vertices++ = (int) (coords - tess_coords) / 3;
+}
+
+void CALLBACK
+wxe_ogla_edge_flag(GLboolean flag)
+{
+}
+
+void CALLBACK
+wxe_ogla_error(GLenum errorCode)
+{
+ const GLubyte *err;
+ err = gluErrorString(errorCode);
+ wxString msg;
+ msg.Printf(wxT("Tesselation error: %d: "), (int)errorCode);
+ msg += wxString::FromAscii((char *) err);
+ send_msg("error", &msg);
+}
+
+void CALLBACK
+wxe_ogla_combine(GLdouble coords[3],
+ void* vertex_data[4],
+ GLfloat w[4],
+ void **dataOut)
+{
+ GLdouble* vertex = tess_alloc_vertex;
+
+ tess_alloc_vertex += 3;
+
+#if 0
+ fprintf(stderr, "combine: ");
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (w[i] > 0.0) {
+ fprintf(stderr, "%d(%g) ", (int) vertex_data[i], w[i]);
+ }
+ }
+ fprintf(stderr, "\r\n");
+ fprintf(stderr, "%g %g %g\r\n", vertex[0], vertex[1], vertex[2]);
+#endif
+
+ vertex[0] = coords[0];
+ vertex[1] = coords[1];
+ vertex[2] = coords[2];
+ *dataOut = vertex;
+}
+
+void init_tess()
+{
+ tess = gluNewTess();
+
+ gluTessCallback(tess, GLU_TESS_VERTEX, (GLUfuncptr) wxe_ogla_vertex);
+ gluTessCallback(tess, GLU_TESS_EDGE_FLAG, (GLUfuncptr) wxe_ogla_edge_flag);
+ gluTessCallback(tess, GLU_TESS_COMBINE, (GLUfuncptr) wxe_ogla_combine);
+ gluTessCallback(tess, GLU_TESS_ERROR, (GLUfuncptr) wxe_ogla_error);
+
+}
+
+void exit_tess()
+{
+ gluDeleteTess(tess);
+}
+
+int wxe_tess_impl(char* buff, ErlDrvTermData caller)
+{
+ ErlDrvBinary* bin;
+ int i;
+ int num_vertices = * (int *) buff; buff += 8; // Align
+ GLdouble *n = (double *) buff; buff += 8*3;
+
+ GLdouble* new_vertices;
+ bin = driver_alloc_binary(num_vertices*6*sizeof(GLdouble));
+ new_vertices = tess_coords = (double *) bin->orig_bytes;
+ memcpy(tess_coords,buff,num_vertices*3*sizeof(GLdouble));
+ tess_alloc_vertex = tess_coords + num_vertices*3;
+
+#if 0
+ fprintf(stderr, "n=%d\r\n", num_vertices);
+#endif
+ int *vertices;
+ vertices = (int *) driver_alloc(sizeof(int) * 16*num_vertices);
+
+ tess_vertices = vertices;
+
+ gluTessNormal(tess, n[0], n[1], n[2]);
+ gluTessBeginPolygon(tess, 0);
+ gluTessBeginContour(tess);
+ for (i = 0; i < num_vertices; i++) {
+ gluTessVertex(tess, tess_coords+3*i, tess_coords+3*i);
+ }
+ gluTessEndContour(tess);
+ gluTessEndPolygon(tess);
+
+ int n_pos = (tess_vertices - vertices);
+
+ int AP = 0; ErlDrvTermData *rt;
+ rt = (ErlDrvTermData *) driver_alloc(sizeof(ErlDrvTermData) * (13+n_pos*2));
+ rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) "_wxe_result_");
+
+ for(i=0; i < n_pos; i++) {
+ rt[AP++] = ERL_DRV_INT; rt[AP++] = (int) vertices[i];
+ };
+ rt[AP++] = ERL_DRV_NIL; rt[AP++] = ERL_DRV_LIST; rt[AP++] = n_pos+1;
+
+ rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) bin;
+ rt[AP++] = (tess_alloc_vertex-new_vertices)*sizeof(GLdouble); rt[AP++] = 0;
+
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Return tuple {list, Bin}
+ rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2; // Result tuple
+
+ driver_send_term(WXE_DRV_PORT,caller,rt,AP);
+// fprintf(stderr, "List %d %d %d \r\n",
+// n_pos,
+// (tess_alloc_vertex-new_vertices)*sizeof(GLdouble),
+// num_vertices*6*sizeof(GLdouble));
+ driver_free_binary(bin);
+ driver_free(vertices);
+ driver_free(rt);
+ return 0;
+}
+