WebGL1のAPIレビュー(2周目)
prev: https://zenn.dev/okuoku/scraps/a0a74834db15e6
next: https://zenn.dev/okuoku/scraps/9e2926081051f7
WebGL1のCバインディングのヘッダファイルを作る
目的 : 実装のためのCヘッダファイルを用意する。
今回のWebGL1 Cバインディング(CWGL)は3つの実装を用意したい。
- WebGL → CWGL 。 以前DOOMを動かしたような、EmscriptenなしでWebGLを使うための実装。
- CWGL → WebGL 。Node.jsでEmscriptenアプリを動かす時 に画面を出す用の実装。
- CWGL → GLES2 。 以前Qiitaに書いた ゲーム専用ブラウザで使う用の実装。ターゲットプラットフォームのネイティブアプリとして動作する。
今回のヘッダファイルは、この3パターン全てで使用される。
(空行の整理)
前回のメソッド削除前のIDLからforkした。
元のWebGLには存在しない基本型。
Context
CWGLのコンテキストは、ヒープ、GPU、その他全ての状態を表現する。全てのAPIは基本的にコンテキストを引数に取り、異なるコンテキストから得られたオブジェクトは他のコンテキストでは使用できない。
struct cwgl_ctx_s;
typedef struct cwgl_ctx_s cwgl_ctx_t;
cwgl_ctx_t* cwgl_ctx_create(int height, int width, int reserved, int flags);
void cwgl_ctx_release(cwgl_ctx_t* ctx);
#define CWGL_CTX_FLAG_HAS_ALPHA (1<<0)
#define CWGL_CTX_FLAG_HAS_DEPTH (1<<1)
#define CWGL_CTX_FLAG_HAS_STENCIL (1<<2)
#define CWGL_CTX_FLAG_ANTIALIAS (1<<3)
#define CWGL_CTX_FLAG_PREMULTIPLIEDALPHA (1<<4)
#define CWGL_CTX_FLAG_PRESERVEDRAWINGBUFFER (1<<5)
コンテキストにはいくつかフラグを供給できる。供給したフラグはあとからクエリも可能となっている。
Query result
ヒープアクセスを伴うAPIは、query result型の値を返却する。多くのクエリはリトライ可能であるため、返却された値を見て再度挑戦できる。
enum cwgl_query_result_e;
typedef enum cwgl_query_result_e cwgl_query_result_t;
Enum, String
デバッグの都合を考えて、GLのenumをC言語的な意味の enum
にしてみる事にした。Khronosのヘッダでは全てのenumは GL_
でプレフィックスされているので、衝突することなく併用できる。
Stringについては前回の通り。size
read
release
の各オペレーションを提供する。 read
はゼロ終端する & size
はゼロ終端を含めたサイズを返す 。 strlen
と挙動が違うことに注意。
enum cwgl_enum_e;
typedef enum cwgl_enum_e cwgl_enum_t;
enumの中身は別のヘッダで与える。
struct cwgl_string_s;
typedef struct cwgl_string_s cwgl_string_t;
size_t cwgl_string_size(cwgl_ctx_t* ctx, cwgl_string_t* str);
cwgl_query_result_t cwgl_string_read(cwgl_ctx_t* ctx, cwgl_string_t* str, char* buf, size_t buflen);
void cwgl_string_release(cwgl_ctx_t* ctx, cwgl_string_t* str);
ユーザオブジェクト (明示的)
ユーザが明示的に作成するオブジェクトは、WebGLでのAPIに加えて、明示的に削除を行う release
APIが必要になる。本来のWebGLではGCに期待している。
WebGLBuffer? createBuffer(); // genBuffers
WebGLShader? createShader(GLenum type);
WebGLProgram? createProgram();
WebGLTexture? createTexture(); // GenTextures
WebGLFramebuffer? createFramebuffer(); // genFramebuffers
WebGLRenderbuffer? createRenderbuffer(); // genRenderBuffers
↓(create
APIは別に宣言する)
struct cwgl_Buffer_s;
struct cwgl_Shader_s;
struct cwgl_Program_s;
struct cwgl_Texture_s;
struct cwgl_Framebuffer_s;
struct cwgl_Renderbuffer_s;
typedef struct cwgl_Buffer_s cwgl_Buffer_t;
typedef struct cwgl_Shader_s cwgl_Shader_t;
typedef struct cwgl_Program_s cwgl_Program_t;
typedef struct cwgl_Texture_s cwgl_Texture_t;
typedef struct cwgl_Framebuffer_s cwgl_Framebuffer_t;
typedef struct cwgl_Renderbuffer_s cwgl_Renderbuffer_t;
void cwgl_Buffer_release(cwgl_ctx_t* ctx, cwgl_Buffer_t* buffer);
void cwgl_Shader_release(cwgl_ctx_t* ctx, cwgl_Shader_t* shader);
void cwgl_Program_release(cwgl_ctx_t* ctx, cwgl_Program_t* program);
void cwgl_Texture_release(cwgl_ctx_t* ctx, cwgl_Texture_t* texture);
void cwgl_Framebuffer_release(cwgl_ctx_t* ctx, cwgl_Framebuffer_t* framebuffer);
void cwgl_Renderbuffer_release(cwgl_ctx_t* ctx, cwgl_Renderbuffer_t* renderbuffer);
ユーザオブジェクト (暗黙的)
WebGLContextAttributes? getContextAttributes();
WebGLActiveInfo? getActiveAttrib(WebGLProgram? program, GLuint index);
WebGLUniformLocation? getUniformLocation(WebGLProgram? program, DOMString name);
WebGLActiveInfo? getActiveUniform(WebGLProgram? program, GLuint index);
WebGLShaderPrecisionFormat? getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
これらはそれぞれ異なるAPI様式となる。
WebGLContextAttributes
これはちょっと良いマッピングが思いうかばなかったので、とりあえずintegerのフラグにした。
WebGLActiveInfo
, WebGLShaderPrecisionFormat
ActiveInfoは数値と文字列の組合せであるため、 get
APIの方で分解する。ActiveInfoを取るAPIは存在しない。ShaderPrecisionFormatも同様。
[Exposed=(Window,Worker)]
interface WebGLActiveInfo {
readonly attribute GLint size;
readonly attribute GLenum type;
readonly attribute DOMString name;
};
[Exposed=(Window,Worker)]
interface WebGLShaderPrecisionFormat {
readonly attribute GLint rangeMin;
readonly attribute GLint rangeMax;
readonly attribute GLint precision;
};
WebGLUniformLocation
これは明示的なユーザオブジェクトと同様に、 release
APIが必要になる。
(実装不要なインターフェースを削除)
3周目 : Arrayを設定するUniform〜vは不要じゃなかった。要修正。
(GLES規格書にないもの)
ちょっと悩んだけど、
- APIで規格上の整数値はenumか
int32_t
等のstdint - メモリサイズなど実行環境に拠るものは
size_t
- boolは
int
という使い分けにしてみた ■ 。
getExtension
は存在しない。ActivateするためのAPIを別途用意した方が良いのかは何とも。。
2章 (GLES2規格書順)
FIXME: vertexAttribPointer
FIXME: BufferDataSource
3章 (GLES2規格書順)
texImage2D の引数が超多いから何か間違えてそう。。
4章 および 5章 (GLES2規格書順)
特に難しいポイントはない。
6章 (GLES2規格書順)
これはキツい。。WebGLやOpenGLでは getUniform
は1つか2つのAPIなのに、CWGLでは型毎に展開する必要があるため、
cwgl_query_result_t cwgl_getUniform_i1(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, int32_t* x);
cwgl_query_result_t cwgl_getUniform_i2(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, int32_t* x, int32_t* y);
cwgl_query_result_t cwgl_getUniform_i3(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, int32_t* x, int32_t* y, int32_t* z);
cwgl_query_result_t cwgl_getUniform_i4(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, int32_t* x, int32_t* y, int32_t* z, int32_t* w);
cwgl_query_result_t cwgl_getUniform_f1(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x);
cwgl_query_result_t cwgl_getUniform_f2(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x, float* y);
cwgl_query_result_t cwgl_getUniform_f3(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x, float* y, float* z);
cwgl_query_result_t cwgl_getUniform_f4(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x, float* y, float* z, float* w);
cwgl_query_result_t cwgl_getUniform_m2(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x);
cwgl_query_result_t cwgl_getUniform_m3(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x);
cwgl_query_result_t cwgl_getUniform_m4(cwgl_ctx_t* ctx, cwgl_Program_t* program, cwgl_UniformLocation_t* location, float* x);
のように長大になってしまう。常識的なプログラムは自分がセットしたuniformをクエリすることは無いので、実装自体サボってしまいたい。。
微調整
エクスポートされる可能性のあるシンボルを CWGL_API
で修飾、cwgl_query_result_t
の列挙型を埋める等。あとGitHubに移動。
Typo 修正
... 以上で終わりだと思ったけどビルドしたらtypoが2箇所あった。今度こそ2周目おわり。