Git Product home page Git Product logo

dart-gl's Introduction

Dart native extension for GLES2

Supports Linux and Windows. OSX is not supported due to inherent incompatibilites in the OSX UI threading model, as well as Apple announcing the discontinuing of support of OpenGL on OSX (https://goo.gl/qQdeQ5).

Steps to generate the bindings

mkdir -p lib/src/generated
pub run tools/gl_generator.dart
clang-format -i --style=Google generated/*.{cc,h}
dartfmt -w generated/*.dart
mv generated/* lib/src/generated/

Limiting bindings to actual symbols

Some GL libraries come with headers that list functions not implemented. This will fail at link time. To avoid this, you can dump the symbols in libGLESv2.so to be used with --limit-api flag intools/gl_generator.dart

nm -D /lib/libGLESv2.so | grep " T " | awk '{print $3}' > limit.txt

Steps to compile the bindings

The previous method for compiling the bindings is no longer available. We are working on a new solution for both Linux and Windows.

In the meantime, the Makefile in the lib/ directory is a good starting point for compiling on Linux.

Functions with interfaces with APIs different from GLES2

If a function's only difference is moving pointer parameters to the return value, it is not listed. See lib/src/manual_bindings.dart for a full list.

  • glGetActiveAttrib doesn't take a bufSize parameter, and returns an ActiveAttrib instance.
  • glGetActiveUniform doesn't take a bufSize parameter, and returns an ActiveAttrib instance.
  • glGetAttachedShaders doesn't take a maxCount parameter, returns a List<int>.
  • glGetProgramInfoLog doesn't take a maxSize parameter, and returns a String.
  • glGetShaderPrecisionFormat returns a ShaderPrecisionFormat instance.
  • glGetShaderSource doesn't take a bufSize parameter and just returns a String.
  • glReadPixels takes a TypedData pixels parameter and the data is put into it, like in the WebGL API. Your program will most likely crash if the TypedData object you pass in is not big enough, or possibly if it's in the wrong format.
  • glShaderSource just takes the parameters int shader and String string. The original API is not really appropriate for Dart.

A note about OpenGL, the Dart VM, and native threads

OpenGL is a thread-bound API. That is, an OpenGL context must be bound (or "made current") on a thread before any other OpenGL functions may be called.

The Dart VM uses a pool of native threads under the hood to carry out tasks on the event queue (overview of the Dart event loop).

This leads to an unfortunate restriction on the use of asynchronous code while making OpenGL calls from Dart. This is bad:

glfwMakeContextCurrent(context);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// other OpenGL calls ...

// Wait for an async task to finish.
await someFuture;

// Draw a triangle.
glDrawArrays(GL_TRIANGLES, 0, 3);
// etc...

The issue is that the context is made current, then there is a call to await, which causes the current task to return to the event loop until someFuture completes. When control returns to the next line, it may be running on a completely different native thread, where the context is not bound.

To avoid this issue, the code must be changed to something resembling the following:

glfwMakeContextCurrent(context);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// other OpenGL calls ...

// Release the context before waiting.
glfwMakeContextCurrent(NULL);

// Wait for an async task to finish.
await someFuture;

// We're back!  Reacquire the context.
glfwMakeContextCurrent(context);

// Draw a triangle.
glDrawArrays(GL_TRIANGLES, 0, 3);
// etc...

This way, the context is released from the thread before control returns to the event loop and then reacquired when it comes back.

Note that this applies to any asynchronous code (not just an await). Here's another bad example:

glfwMakeContextCurrent(context);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// other OpenGL calls ...

// Load an image, then create a texture.
var f = new File("image.rgb");
f.readFileAsBytes().then((bytes) {
  var tex = glGenTextures(1);
  glBindTexture(GL_TEXTURE_2D, tex);
  glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, width, height, 0, GL_UNSIGNED_BYTE,
      GL_RGBA, bytes);
});

// etc...

In this case, there's no guarantee that the callback to the Future returned by readFileAsBytes would be running on the same thread as the original task.

In practice, most OpenGL code is written synchronously, as it's generally not advisable to be waiting for other tasks to complete while in the middle of rendering a frame. However, it's important to be aware of this restriction. When making OpenGL calls, either avoid awaiting asynchronous methods and making OpenGL calls in async callbacks, or properly release the context anytime control returns to the event loop, and reacquire it when ready to make OpenGL calls again.

dart-gl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dart-gl's Issues

glGetIntegerv always returns one value, but the spec allows for multiple

From @exavolt:
"""
I've found an implementation incompatibilities of glGet* functions. From the spec1, a glGet* function might returns one or more values which varies between parameters. For example, glGetIntegerv(GL_ACTIVE_TEXTURE) returns only one value, while something like glGetIntegerv(GL_VIEWPORT) would return four values. The binding always assume that the functions return only one value which, in many cases, it makes the functions practically useless because they returned only the first value.

I think that this could cause a more serious issue, i.e., buffer overrun, because the buffer provided to hold the returned values might be smaller than the number of value asked by the parameter.

The updated implementation should use a map of parameter names with their respective expected number of values as defined in the spec1. On call, the binding function will allocate the appropriately-sized buffer based on the parameter name before calling its respective actual glGet function.

  • rez

"""

Issue on README.md

on README.md, it worte: pub run tools/gl_generate.dart, but the dart file name in tools directory is gl_generator.dart, typo, right?

Support for Android and iOS

Sorry for opening an issue to ask this, but couldnt find the answer clearly anywhere, and didnt find a forum for the project to ask this.

Im investigating if it is possible to migrate an open source game engine to DART/Flutter. That game engine is for Android and iOS games. Right now Im checking the interface between the engine and OpenGL, so I ended up here. Im no expert (far from it) in OpenGL, so bear with me.

Is Android supported? I see on the docs that Linux is supported, but Android is never mentioned anywhere, and it's not clear to me that this implies that Android is supported as well. If so, any idea on which Android versions it works or have been tested?

From the readme it seems iOS is not supported, any pointers on what would be my alternatives?

How good is the performance

Hi, @jtmcdole, thanks for your comments on my issues.

And How good is the performance of this native extension? Do you have any benchmark on this library yet?

Status of project?

Does this still work for Windows as of 9/1/2019? If so, is there a less confusing step-by-step on how to get this running out there?

I noticed this:

The previous method for compiling the bindings is no longer available. We are working on a new solution for both Linux and Windows.

In the meantime, the Makefile in the lib/ directory is a good starting point for compiling on Linux.

Does this mean we are not able to compile the bindings currently? If so, why?

Thanks for any help.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.