ptitSeb / gl4es

GL4ES is a OpenGL 2.1/1.5 to GL ES 2.0/1.1 translation library, with support for Pandora, ODroid, OrangePI, CHIP, Raspberry PI, Android, Emscripten and AmigaOS4.
http://ptitseb.github.io/gl4es/
MIT License
696 stars 159 forks source link

Build without EGL or X11 #47

Closed kas1e closed 6 years ago

kas1e commented 6 years ago

Want to port gl4es to some obscure platform, which have no EGL or X11, but its own API for creating context and co, and have some questions:

Lately port REGAL and it wasn't as good as i expected. Simple things do not works as expected while others do. So i want to try gl4es as it seems only one project which in develop and looks good enough.

So, i can buld Regal as static library, just with: -DREGAL_SYS_ES2=1 -DREGAL_STATIC_ES2 -DREGAL_SYS_X11=0 -DREGAL_SYS_GLX=0 -DREGAL_SYS_EGL=0

Then, in GL programm i just change include <GL/gl.h> on include <GL/Regal.h>, and link binary against -lgles2 , and all works.

So i want to do the same for gl4es. Is it possible ? All i need, its static library, which will worry about ogl calls and transfer them to ogles context (which i create myself, by own api) , without reling in any way on X11 or EGL (as i can for myself create windows, context and handle buttons and stuff).

Thanks in advance for help !

ptitSeb commented 6 years ago

The Android path is "no-X11", so this can be used I guess. I can add a "NOX11" option in the CMakeList if needed.

But no EGL? I'm not sure how to do that. How do you call eglGetProcAdress if you have no EGL?

nintendontit commented 6 years ago

no-x11 is very nice if you can. And can you add support to Tinker Board?

kas1e commented 6 years ago

@ptitSeb Yeah, -DNOX11 will be good. Or something like -DHAVE_X11=1 (or 0 if not).

As for EGL : i do not know gl4es code well at moment,, but is EGL absolutly requement ? For what there is necessarity to call eglGetProcAdress ? Can't we make it all "static" or at least optional ?

I mean, let it be coder later choice what he want, EGL, SDL, X11, WGL, GLES, GLUT or whatever else. But make it all independent from core of gl4es.

I may talking bull, as i do not know internals of gl4es at moment , but do not create any context, , it user in users's gl code will create it by any api he wish (native, sdl, x11, egl, does not matter). Just after user create his context, he may call some new gl4es function called "gl4es_make_current_context(ogles_context);" , and that all.

Of course, maybe gl4es is very different from that, but, if we can get rid of EGL necessarity, it will mean that any kind of device / OS / whatever which have GLES2 , will be able to use gl4es.

ptitSeb commented 6 years ago

I will work on NO_X11 / HAVE_X11 flags (not sure wich one yet).

About EGL. gl4es dynamicaly link to the GLES backend at runtime. And it also does that with the EGL library. eglGetProcAdress is needed to get extension function. But that function may be part of the GLES2 driver? In that case, using LIBGL_EGL=libGLESv2.somay be enough.

ptitSeb commented 6 years ago

Also, EGL is needed for eglSwapBuffers that is quite important.

ptitSeb commented 6 years ago

Commit cc810ff8209fcf7f74563f6f3ab2f4bb0bb99bba added NOX11 option in cmake.

@kas1e: For no EGL, it's really is more tricky and I'm not sure how to proceed. EGL is used at minimum in 3 places (beside the GLES context creation):

  1. At init, to create a small pbuffer to get Hardware information support. This part can be skipped with LIBGL_NOTEST=1
  2. For eglGetProcAddress to get extension function adresses.
  3. for eglSwapBuffers to swap buffers (actually put drawing onscreen).

@nintendontit: I don't have a Tinker Board, but if there is some specific default settings or anything, I can add some support, but I need dirrection as I cannot test anything.

kas1e commented 6 years ago

@ptitSeb If you even consider it as option to think about (i mean to build with disabled EGL), that good !

For first 2 i need to think about , but as for 3 : imho, gl4es should't do any "swapbuffers",it should do user's GL code ? I.e. if he will use egl, he will use eglSwapBufers, if he will use SDL, then he will use SDL_GL_SwapBuffers(). I.e. user in his code should do it all imho ?

kas1e commented 6 years ago

@ptitSeb Aha i see, #1 can be skipped alredy, that good. We can just add to some main include later something like

ifndef SYS_EGL

define LIBGL_NOTEST=1

endif

So part 1 will be skipped already.

ptitSeb commented 6 years ago

For the No_EGL, I'm ok to do something like that, but I realy have no clue on what to use instead for the 2. and 3.

gl4es is a "full" OpenGL driver (like mesaGL). So, function like SDL_GL_SwapBuffer() usualy call glXSwapBuffers(...) from gl4es! If you have a working SDL_GL_SwapBuffers, can I use the same code in gl4es than in SDL then to actualy swap the Buffers. How do you compile your SDL(2?.) for your hardware?

kas1e commented 6 years ago

gl4es is a "full" OpenGL driver (like mesaGL). So, function like SDL_GL_SwapBuffer() usualy call glXSwapBuffers(...) from gl4es!

Probaly we need to create private function in gl4es called gl4es_SwapBuffers, and use that everywhere where for now eglSwapBuffer is used. And, it can be some file like gl4es_swapbuffer.c , in which:

ifdef (SYS_EGL)

void gl4es_SwapBuffers() { EGL_SwapBuffer(); }

else // no SYS_EGL

ifdef _linux

void gl4es_SwapBuffers() { X11_SwapBuffer(); }

endif

ifdef amigaos4

void gl4es_SwapBuffers() { aos4_SwapBuffer(); }

endif

ifdef any_other_platform

void gl4es_SwapBuffers() { ANYSPECIFICPLATFORM_SwapBuffer(); }

endif

So, when user will call from sdl code SDL_GL_SwapBuffers , or from GLUT glu_SwapBuffer(), or from anything else, it will call directly gl4es_SwapBuffer(), code of which, will be platform related. And the once that done, anyone can easyly add his own supported code.

So probably with that one we can cover everything. Even add some warning ifdef like "platform not supported, write your swap-code there!".

On my platform i use ogles2.library that way:

  1. i open ogles2.libary
  2. i create window
  3. i create ogles2 context and attach window to it
  4. i make that context as current one: aglMakeCurrent(ogles_context);
  5. call rendering part in which i call aglSwapBuffers();

So, probably, with gl4es, in my code i will have needs to just call "gl4es_SwapBuffer" which will call aglSwaBuffer().

But then, for example in Regal, there is no "swapbuffer" calls. Its just pure translate one calls to another and mimic missing ones.

I mean, is there needs at all to have in gl4es "swapbuffer" function, as we anyway transfer it all to ogles2, which driver by itself have his own swapbuffer functinos, whcih user later will use ?

As for #2, need to think about more ..

ptitSeb commented 6 years ago

Does a aglGetProcAddress exist? Also, is there a libAGL.dylib or is everything inside libGLESv2?

kas1e commented 6 years ago

Does a aglGetProcAddress exist? No, only those ones are platform specific:

    aglCreateContext
    aglCreateContextTags
    aglDestroyContext
    aglMakeCurrent
    aglSwapBuffers
    aglSetBitmap

Also, is there a libAGL.dylib or is everything inside libGLESv2? Everything inside, so i want to build just static version (probably as for Android currently?).

Probably GetProcAddress need it only when library is shared ?

ptitSeb commented 6 years ago

So I guess this is for iOS. I have to do some test. Currently, gl4es rely on dlopen / dlsym, and I'm not sure this works well on staticaly linked library. And moving to not using dlsym will be tricky (for example, a call to glTextureImage2D needs to go to gl4es, that in turn will call GLES2 glTextureImage2D).

kas1e commented 6 years ago

Will be good if we can build 2 versions, let's say shared as it now : so dlopen / dlsym, etc. And static one, without it.

Thanks for help with !

ptitSeb commented 6 years ago

@kas1e with commit 2c43cc460bea3b545e06d946d6560b0c53c8ea3d I have added an NOEGL compile option. It should be working for you now. Some gidelines:

I assume this is for Amiga / Warp3D in fact, if you want some AMIGA or WARP3D (or somthing else) compile option with some default stuff, tell me...

kas1e commented 6 years ago

@ptitSeb Thanks a bunch ! Yes, its for amigaos4/warp3d (opegles2.library sits on top of warp3d).

I downloaded latest trunk, and to avoid hassle with CMAKE (at first tests), create some simple build makefile (amigaos4_build.sh): http://kas1e.mikendezign.com/aos4/gl4es/amigaos4_build.sh

We can later or add it as it, or i can include it to CMAKE once all will be compiles.

So, once i run first string to build array.c, it bring me 2 kind of errors

  1. From gl.h : there include of EGL headerrs (so i have #platform unsupported" and other related errors). Probably we still need to add flags like HAVE_EGL=0 / HAVE_EGL = 1 as well as HAVE_X11 =0 and HAVE_X11 = 1 , because for example now,, in gl.h , we need to do something like:

ifdef HAVE_EGL

include <EGL/egl.h>

endif

But as we have only NOEGL switch, we need to do it like:

ifndef HAVE_EGL

//skip

else

include <EGL/egl.h>

endif

Reads much harder :)

Also starting from lines 60 till 120 there is lots of typedefs for EGL whih also need to #ifdefs.

And, another issue more general:

src/gl/stack.h:150: error: redefinition of typedef 'glstack_t' src/gl/state.h:19: note: previous declaration of 'glstack_t' was here src/gl/stack.h:175: error: redefinition of typedef 'glclientstack_t' src/gl/state.h:20: note: previous declaration of 'glclientstack_t' was here

GCC i use : 4.4.3 if that make differences.

Thanks a bunch, again !

ptitSeb commented 6 years ago

Ok, I'm reworking the NOEGL to be sure I don't use any EGL code in this path. It should be ok with next commit.

Also, the "error: redefinition" you see is because that old gcc doesn't like my forward declare of the structure. I have also reworked the headers and removed those 2 forward declares.

Hopefully next commit will build for you.

About your build script, I can integrate it in the github once everything works, sure (cmake is quite handy because it's easier to write a simple CMakeList.txt than a simple Makefile, but I understand that cmake needs a lots of dependancy to build).

ptitSeb commented 6 years ago

@kas1e commit 3b731bd0b63adce1d1d97140437e11727cc64835 should build for you now.

(also, one note, but I haven't paid much attention to BIGENDIAN until now, so you can expect some bad colors on some textures... We'll fix that later when gl4es works).

kas1e commented 6 years ago

@ptitSeb Thanks ! Almost builds now !

There is only few little errors remainin:

in framebuffers.c and init.c , there is execinfo.h, which not included only for androin, we also need to disable it for amigaos4, currently i do it like:

if !defined (ANDROID) && !defined(amigaos4)

include

endif

also last error is in loader.c:

linux/limits.h: No such file or directory, and so 'PATH_MAX' undeclared (first use in this function)

So we can thre do it like:

ifdef amigaos4

include

else

include <linux/limits.h>

endif

But i am not sure if loader.c is need it at all, if i will use it statically at first tests ..

So, with those changes i am able to build all objects. Now i can probably just do:

$ ppc-amigaos-ar cr libgl4es.a *.o $ ppc-amigaos-ranlib libgl4es.a

And so when build test example, then add -lgl4es.

Then some simple test like:

include <GL/gl4es.h>

int main() { glBegin ( GL_POLYGON ); glEnd(); }

And just : ppc-amigaos-gcc test.c -o test -lgl4es

Will take some minuts to try

As for endianes - yeah, once it will start render something, then.

ptitSeb commented 6 years ago

Ok, I'll add a new platform to the cmake build (even if you don't use it). I'll call AMIGAOS4 all capital, for consistancy with all other define.

For the simple test, don't forget gl4es is "just" an OpenGL driver, so you simply need to #include "GL/gl.h" There is a gl4eshint.h then can be usefull, but its just some #define to be used with glHint(...) to activate / deactivate some of gl4es parameter at runtime.

kas1e commented 6 years ago

Thanks for adding amigaos4 !

As for first test : i go to the src/gl/ directory, and there create test.c file in which:

include "gl.h"

int main() { glBegin ( GL_POLYGON ); glEnd(); }

Then when i trying to compile it , it scream about:

In file included from gl.h:3, from test.c:1: gles.h:3:29: error: GLES/glplatform.h: No such file or directory

Thats right for amigaos4, as we have in our SDK only that:

GLES2/gl2.h GLES2/gl2ext.h GLES2/gl2platform.h

Probably need to tweak gl.h as well

ptitSeb commented 6 years ago

You need a regular gl.h from any OpenGL platform. Don't use the ones inside gl4es sources, there are just used for building gl4es.

Or use the one inside include/GL, it's a standard mesa version if you need one (but rally, this copy is old, a newer one, handling at least OpenGL 2.1, would be better).

kas1e commented 6 years ago

Rigth, tried like that:

include "../../include/GL/gl.h"

int main() { glBegin ( GL_POLYGON ); glEnd(); }

Then

$ ppc-amigaos-gcc test.c -Llibgl4es.a /tmp/ccJ2XoMw.o: In function main': test.c:(.text+0x18): undefined reference toglBegin' test.c:(.text+0x1c): undefined reference to `glEnd' collect2: ld returned 1 exit status

Should't we also include something from gl4es still ?

ptitSeb commented 6 years ago

doesn't the command should be ppc-amigaos-gcc test.c -lgl4es (with a small -l to link a library, not a capital -L that define an alternative path for library) or a simple ppc-amigaos-gcc test.c libgl4es.a should work too

kas1e commented 6 years ago

Sorry, was messed with -L and -l , so i do doing it like this from src/gl directory:

$ ppc-amigaos-gcc test.c -L../objects -lgl4es

And have lots of undefs like:

http://kas1e.mikendezign.com/aos4/gl4es/gl4es_first_linking.txt

ptitSeb commented 6 years ago

Ok

First, you need to add -ldl to your test (and I hope libdl exists on AmigaOS4). Second, you need to also compile src/glx/*.c (don't worry, the #ifdef should take care of the true glx code).

kas1e commented 6 years ago

We have libdl, but its pain , always have problems and bugs. It dlsym and stuff still need it even if we build static library ?

As for glx, is it enough to compile only 4 files as for android, or need to compile all 6 ?

(and thanks again to spend your time on it)

ptitSeb commented 6 years ago

Yes, dlopen / dlsym are needed even if gl4es is build as a static library. The GLES2 library is open using dlopen, and all function grabbed using dlsym. The lib will not work without libdl in it's current state.

The 4 files like Android should be enough. The other 2 will not contain any code with "NOX11" defined.

You're almost there! :)

kas1e commented 6 years ago

Trying to build glx/ direcotry , and glx.c also need to be changed on:

if !defined (ANDROID) && !defined(amigaos4)

include

endif

But even ater that , it bring me bunch of new errors:

http://kas1e.mikendezign.com/aos4/gl4es/glx_c_errors.txt

ptitSeb commented 6 years ago

Mmm, I'll add AMIGAOS4 on glx.c, sure.

But the errors you have now, I don't really understand why the src/gl/gl.h compile without issues for all src/gl/*.c file and not for src/glx/glx.c

ptitSeb commented 6 years ago

The error are because all the khronos_*_t typedef are not defined. I suspect #include <GLES/glplatform.h> doesn't open the file inside gl4es/include folder.

kas1e commented 6 years ago

Oh sorry, its me bork gl/gles.h a bit (tryied to fix previous errors when run test case), now rewert back and will try to compil glx , sorry

kas1e commented 6 years ago

Ok compile 4 objects (same as for android), and add it to the libgl4es.a, as well as add -ldl , so, there is much less errors, but stil some are: http://kas1e.mikendezign.com/aos4/gl4es/gl4es_second_linking.txt

ptitSeb commented 6 years ago

I think something went wrong with the build of src/gl/init.c and src/gl/framebuffers.c

(EDIT maybe you forgot the #endif after the #include <execinfo.h> for both files?)

kas1e commented 6 years ago

Doh, its just i miss init.o object from link library ! damn, probably forget to rebuild after fixing execinfo.h

Now, only those errors remain:

glx.c:(.text+0xd4): undefined reference to backtrace' glx.c:(.text+0x104): undefined reference tobacktrace_symbols_fd' libgl4es.a(glx.o): In function glx_init': glx.c:(.text+0x3dc): undefined reference torpi_init'

And few related to our -ldl ..

Btw, our libraries its not .so libraries, they "amiga libraries", so they shared in their own way, and dunno if dlsym will works on ogles2.library at all..

ptitSeb commented 6 years ago

so the ogles2 library name is "ogles2.library". And where is it located?

kas1e commented 6 years ago

in LIBS: directory But we usually use this piece of code when want to open it from amiga code:

OpenLibrary("ogles2.library", 0);

(system know where to open it)

ptitSeb commented 6 years ago

Commit 8047e2f886fd4f581c64d26adbd9f93ccab8fbca should have fixed the last undefined. Also, I have coded the correct name for ogles2 lib.

Now, if dlopen/dlsym is not good on AmigaOS4, do you have alternative? OpenLibrary(...) does the same as dlopen(...)?

kas1e commented 6 years ago

Downloaded last commit, rebuild everything from scratch: library done, test case compiles without linking error. Yammi ! :)

Through to note, in the LIBS without "/" , and with ":" at end , i.e. full path from the root will be LIBS:ogles2.library (we don't have "/" for root).

As for that dlopen/dlsym .. Can you plz describe me a bit more what dlopen/dlsym do for real, i.e. its open dynamic .sobj library, and then read from it some symbols table where found names of the functions ? If so, then yep, dlopen/dlsym there will not works..

Probably, easy way there can be done some generall way (can be done for all platforms, which want to build gl4es in "static" form): we can make a file, with full list of OGLES2 functions (154 or how much of them by kronos's specification). And so, make list of defines, like

define blabllbbal1 glDrawElemets

define blalblblala2 glAttachShader

etc

And on linking stage, it will undefs about those symbols, but then, i will add -lgles2 , and all will be fine. Other ones will add their -lglesXX if will compile static versions.

ptitSeb commented 6 years ago

I'll fix the LIBS:.

For dlopen/dlsym. dlopen open an handle, and "load" a dynamic library. Then, with dlsym, you get address of a function based on it's name. gl4es works like this: for example, if your program use glDrawElements(...) Because you are linked (staticaly or dynamcaly) to gl4es, you call the glDrawElements(...) from gl4es, that is an alias for gl4es_glDrawElements(...) This fonction will do some specific stuff, depending on the parameters used (for example, you can call with GL_QUADS that is not supported on OGLES2, but is supported on full OpenGL, and gl4es will handle that as well). At some point, gl4es will call the "real" glDrawElements(...) from OGLES2 driver, so it will get the function pointer using dlsym(gles, "glDrawElements") and call that function, so the GLES2 driver can draw the things. All call in gl4es are wrapped in a similar way. You never call function from the GLES2 driver directly. It gl4es that does it. And gl4es will make some optimisation, cache things, and limits the number of calls to GLES2 driver to try get more speed...

kas1e commented 6 years ago

Ok got it, thanks for explain :)

One of our developers say that if i need to find out the function addresses in ogles2.library, "use the source": https://github.com/AmigaPorts/sdl2-amigaos4/blob/master/src/video/amigaos4/SDL_os4opengles2wrapper.c

As i see, there is list of all GLES functions, then, some functions define called AmiGetGLESPROC(); , then they fill "table" , and then, probably that functino used.

I will ask for more details.

Thanks a bunch that you worry so deep about all this :)

ptitSeb commented 6 years ago

I'm not confident this will work. You will have name collision between the ogles2 function name and gl4es funciton name, that will be the same. That's why I use dlopen on gl4es. the glXXX name of gl4es are the one to be used by the program, and the glXXX name of ogles2 are the one used only by gl4es. But those are the same name, so if you link with both ogles2 and gl4es, how to know wich one to use? Or maybe I haven't understood how that OpenLib works...

I must insist, gl4es is not working like Regal. Regal create some new function, with a different name, where gl4es create full OpenGL functions. I have not created any "mangling" mecanism for gl4es. gl4es is an OpenGL library: you put it in your system and you use OpenGL program without recompiling.

Now, can I just use that AmigaGetGLESProc(...) function from SDL? will it give the ogles2 function pointer without masking the gl4es function?

ptitSeb commented 6 years ago

@kas1e : I don't know OS4, but if I understand this http://amigacoder.x10.mx/tutorial/os4_libs.html correctly, and if I take the sources from https://github.com/AmigaPorts/sdl2-amigaos4/blob/master/src/video/amigaos4/SDL_os4library.c and https://github.com/AmigaPorts/sdl2-amigaos4/blob/master/src/video/amigaos4/SDL_os4opengles.c, can I have access to OGLES2 function using IOGLES2->glXXXX(...). It's strange because https://github.com/AmigaPorts/sdl2-amigaos4/blob/master/src/video/amigaos4/SDL_os4opengles2wrapper.c doesn't seems to use the Library Interface at all.

kas1e commented 6 years ago

Its just in thise part of codein SDL2, its only about that fucntions to get address, but then, there: https://github.com/AmigaPorts/sdl2-amigaos4/blob/master/src/video/amigaos4/SDL_os4opengles.c You may see functions like:

OS4_GLES_LoadLibrary() - that one open library, and interface. OS4_GLES_GetProcAddress() - that one use AmiGetGLESProc()

Probably we can mix from it what we need ..

kas1e commented 6 years ago

I.e. we usally do it like this : open library, open interface of library and use fucntinos from library like LIBNAME->function_from_library, then once we done, we close interface, close library, and exit.

ptitSeb commented 6 years ago

Ok, then I can probably try to do that in gl4es. Using IOGLES2->glXXX will ensure I'm not mixing gl4es and gles2 function, so that's good.

I assume the OGLES2 Interface is defined in in the #include <proto/ogles2.h> statement?

I'll go to bed now, but I'll try to write some code for that tomorrow (I will not be able to test the code at all, as I have no Amiga at home). I'll do specific Amiga code in loader.c...

kas1e commented 6 years ago

Just add it as you think it should works, and then i will adapt it later with all necessary headers and stuff. But you are right about proto/ogles2.h

There is some little test-case i cookie for test Regal build before: http://kas1e.mikendezign.com/aos4/gl4es/os4_gles_example_for_ptitSeb.c

There i do: open ogles2.library open interface of it create window by internal amiga api create context by OGLES2 fucntions make context be current draw the stuff close interface/context and exit

kas1e commented 6 years ago

@ptitSeb Talked to another developer which know amigaos4 internals very well, and that whay he say:

Use the interface to the ogles2.library directly rather than any stub library, that you might use for compiling simplicity. olgesSomeFunc() will not then clash with IOgles->olglesSomefunc(). The library could be opened in a constructor, it need not be opened in the link lib. The Interface could be extern to the new library and provided in the users code. the new lib would just need to be compiked with

include proto/ogles2.h

Seems so its kind of prove about the way you want to add it, but it also mean we may have no needs to open ogles2.library from the gl4es at all , it can be done from user's code, as in example i provide few post early.

ptitSeb commented 6 years ago

@kas1e : with commit ba6666116b4bd41a4a4430ada2837563294ab360 I have rewrote the loader. It should be OS4 compatible now, and libdl is not used anymore (hopefully). As I cannot even compile on my side, expect some error.

Now, to go further, and for gl4es to provide a working copy of all aglXXX function (so you don't need at all to Interface with ogles2 in the program), I'll need a copy of proto/ogles2.h so I can copy the same structure and function prototype.

kas1e commented 6 years ago

@ptitSeb Woah ! Tested: http://kas1e.mikendezign.com/aos4/gl4es/loader.txt

As for gles2 sdk, there is: http://kas1e.mikendezign.com/aos4/gl4es/gles2_os4_includes.zip

Through, i am not sure if we need to add to gl4es opening of library, obtaining real interfaces etc. We can just extern interface, and use those IOGLES2->glXXX calls. Then, when user will write his programm,he will just ourself open library, and so on. And on linking stage, its all will be fine.

But that can be deal with later of course, first thing to make it render anything :)

Thanks !