1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2008-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #include <stdio.h>
22 #include <string.h>
23 #ifndef _WIN32
24 #include <dlfcn.h>
25 #else
26 #include <windows.h>
27 #endif
28 #include "wxe_impl.h"
29 #include "wxe_return.h"
30 #include "wxe_gl.h"
31 
32 /* ****************************************************************************
33  * Opengl context management *
34  * ****************************************************************************/
35 
36 int erl_gl_initiated = FALSE;
37 ErlDrvTermData gl_active = 0;
38 wxeGLC glc;
39 
40 typedef void (*WXE_GL_DISPATCH) (int, char *, ErlDrvPort, ErlDrvTermData, char **, int *);
41 WXE_GL_DISPATCH wxe_gl_dispatch;
42 
43 #ifdef _WIN32
44 #define RTLD_LAZY 0
45 typedef HMODULE DL_LIB_P;
dlsym(HMODULE Lib,const char * func)46 void * dlsym(HMODULE Lib, const char *func) {
47   void * funcp;
48   if((funcp = (void *) GetProcAddress(Lib, func)))
49     return funcp;
50   else
51     return (void *) wglGetProcAddress(func);
52 }
53 
dlopen(const char * path,int unused)54 HMODULE dlopen(const char *path, int unused) {
55   WCHAR * DLL;
56   int len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
57   DLL = (WCHAR *) malloc(len * sizeof(WCHAR));
58   MultiByteToWideChar(CP_ACP, 0, path, -1, DLL, len);
59   HMODULE lib = LoadLibrary(DLL);
60   free(DLL);
61   return lib;
62 }
63 
dlclose(HMODULE Lib)64 void dlclose(HMODULE Lib) {
65   FreeLibrary(Lib);
66 }
67 #else
68 typedef void * DL_LIB_P;
69 #endif
70 
wxe_initOpenGL(wxeReturn * rt,char * bp)71 void wxe_initOpenGL(wxeReturn *rt, char *bp) {
72   DL_LIB_P LIBhandle;
73   int (*init_opengl)(void *);
74 #ifdef _WIN32
75   void * erlCallbacks = &WinDynDriverCallbacks;
76 #else
77   void * erlCallbacks = NULL;
78 #endif
79 
80   if(erl_gl_initiated == FALSE) {
81     if((LIBhandle = dlopen(bp, RTLD_LAZY))) {
82       *(void **) (&init_opengl) = dlsym(LIBhandle, "egl_init_opengl");
83       wxe_gl_dispatch = (WXE_GL_DISPATCH) dlsym(LIBhandle, "egl_dispatch");
84       if(init_opengl && wxe_gl_dispatch) {
85 	(*init_opengl)(erlCallbacks);
86 	rt->addAtom((char *) "ok");
87 	rt->add(wxString::FromAscii("initiated"));
88 	rt->addTupleCount(2);
89 	erl_gl_initiated = TRUE;
90       } else {
91 	wxString msg;
92 	msg.Printf(wxT("In library: "));
93 	msg += wxString::FromAscii(bp);
94 	msg += wxT(" functions: ");
95 	if(!init_opengl)
96 	  msg += wxT("egl_init_opengl ");
97 	if(!wxe_gl_dispatch)
98 	  msg += wxT("egl_dispatch ");
99 	rt->addAtom((char *) "error");
100 	rt->add(msg);
101 	rt->addTupleCount(2);
102       }
103     } else {
104       wxString msg;
105       msg.Printf(wxT("Could not load dll: "));
106       msg += wxString::FromAscii(bp);
107       rt->addAtom((char *) "error");
108       rt->add(msg);
109       rt->addTupleCount(2);
110     }
111   } else {
112     rt->addAtom((char *) "ok");
113     rt->add(wxString::FromAscii("already initilized"));
114     rt->addTupleCount(2);
115   }
116   rt->send();
117 }
118 
setActiveGL(ErlDrvTermData caller,wxGLCanvas * canvas)119 void setActiveGL(ErlDrvTermData caller, wxGLCanvas *canvas)
120 {
121   gl_active = caller;
122   glc[caller] = canvas;
123 }
124 
deleteActiveGL(wxGLCanvas * canvas)125 void deleteActiveGL(wxGLCanvas *canvas)
126 {
127   gl_active = 0;
128   wxeGLC::iterator it;
129   for(it = glc.begin(); it != glc.end(); ++it) {
130     if(it->second == canvas) {
131       it->second = (wxGLCanvas *) 0;
132     }
133   }
134 }
135 
gl_dispatch(int op,char * bp,ErlDrvTermData caller,WXEBinRef * bins)136 void gl_dispatch(int op, char *bp,ErlDrvTermData caller,WXEBinRef *bins){
137   if(caller != gl_active) {
138     wxGLCanvas * current = glc[caller];
139     if(current) {
140       if(current != glc[gl_active]) {
141 	current->SetCurrent();
142       }
143       gl_active = caller;
144     } else {
145       ErlDrvTermData rt[] = // Error msg
146 	{ERL_DRV_ATOM, driver_mk_atom((char *) "_egl_error_"),
147 	 ERL_DRV_INT,  (ErlDrvTermData) op,
148 	 ERL_DRV_ATOM, driver_mk_atom((char *) "no_gl_context"),
149 	 ERL_DRV_TUPLE,3};
150       erl_drv_send_term(WXE_DRV_PORT,caller,rt,8);
151       return ;
152     }
153   };
154   char * bs[3];
155   int bs_sz[3];
156   for(int i=0; i<3; i++) {
157     if(bins[i].from) {
158       bs[i] = bins[i].base;
159       bs_sz[i] = bins[i].size;
160     }
161     else
162       break;
163   }
164   wxe_gl_dispatch(op, bp, WXE_DRV_PORT_HANDLE, caller, bs, bs_sz);
165 }
166 
167