diff --git a/scripts/bgfx-idl.lua b/scripts/bgfx-idl.lua new file mode 100644 index 000000000..f0d57fefa --- /dev/null +++ b/scripts/bgfx-idl.lua @@ -0,0 +1,93 @@ +-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved. +-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE + +local idl = require "idl" +local codegen = require "codegen" + +assert(loadfile("bgfx.idl" , "t", idl))() + +codegen.nameconversion(idl.types, idl.funcs) + +local code_temp_include = [[ +/* + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +/* + * + * AUTO GENERATED! DO NOT EDIT! + * + */ + +$c99decl +/**/ +typedef struct bgfx_interface_vtbl +{ + $interface_struct +} bgfx_interface_vtbl_t; +]] + +local code_temp_impl = [[ +/* + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +/* + * + * AUTO GENERATED! DO NOT EDIT! + * + */ + +$c99 +/**/ +BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version) +{ + if (_version == BGFX_API_VERSION) + { + static bgfx_interface_vtbl_t s_bgfx_interface = + { + $interface_import + }; + + return &s_bgfx_interface; + } + + return NULL; +} +]] + +local function codes() + local temp = {} + local action = { + c99 = "\n", + c99decl = "\n", + interface_struct = "\n\t", + interface_import = ",\n\t\t\t", + } + for k in pairs(action) do + temp[k] = {} + end + for _, f in ipairs(idl.funcs) do + for k in pairs(action) do + table.insert(temp[k], (codegen["gen_"..k](f))) + end + end + + for k, ident in pairs(action) do + temp[k] = table.concat(temp[k], ident) + end + + return temp +end + +local codes_tbl = codes() + +for filename, temp in pairs { + ["../include/bgfx/c99/bgfx.idl.h"] = code_temp_include , + ["../src/bgfx.idl.inl"] = code_temp_impl } do + + print ("Generate " .. filename) + local out = io.open(filename, "wb") + out:write((temp:gsub("$([%l%d_]+)", codes_tbl))) + out:close() +end diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl new file mode 100644 index 000000000..11a1674e9 --- /dev/null +++ b/scripts/bgfx.idl @@ -0,0 +1,955 @@ +-- bgfx interface + +typedef "bool" +typedef "char" +typedef "float" +typedef "int32_t" +typedef "uint8_t" +typedef "uint16_t" +typedef "uint32_t" +typedef "uint64_t" +typedef "uintptr_t" +typedef "va_list" +typedef "void" + +typedef "Attachment" +typedef "Caps" +typedef "Encoder" +typedef "Init" +typedef "InstanceDataBuffer" +typedef "InternalData" +typedef "Memory" +typedef "PlatformData" +typedef "ReleaseFn" +typedef "Stats" +typedef "TextureInfo" +typedef "Transform" +typedef "TransientIndexBuffer" +typedef "TransientVertexBuffer" +typedef "UniformInfo" +typedef "VertexDecl" +typedef "ViewId" + +typedef.Access { enum } +typedef.Attrib { enum } +typedef.AttribType { enum } +typedef.BackbufferRatio { enum } +typedef.OcclusionQueryResult { enum } +typedef.RenderFrame { enum } +typedef.RendererType { enum } +typedef.TextureFormat { enum } +typedef.TopologyConvert { enum } +typedef.TopologySort { enum } +typedef.UniformType { enum } +typedef.ViewMode { enum } + +typedef.DynamicIndexBufferHandle { handle } +typedef.DynamicVertexBufferHandle { handle } +typedef.FrameBufferHandle { handle } +typedef.IndexBufferHandle { handle } +typedef.IndirectBufferHandle { handle } +typedef.OcclusionQueryHandle { handle } +typedef.ProgramHandle { handle } +typedef.ShaderHandle { handle } +typedef.TextureHandle { handle } +typedef.UniformHandle { handle } +typedef.VertexBufferHandle { handle } +typedef.VertexDeclHandle { handle } + +func.VertexDecl.begin + "void" + .renderer "RendererType::Enum" + +func.VertexDecl.add + "void" + .attrib "Attrib::Enum" + .num "uint8_t" + .type "AttribType::Enum" + .normalized "bool" + .asInt "bool" + +func.VertexDecl.decode { const } + "void" + .attrib "Attrib::Enum" + .num "uint8_t &" { out } + .type "AttribType::Enum &" { out } + .normalized "bool &" { out } + .asInt "bool &" { out } + +func.VertexDecl.has { const } + "bool" + .attrib "Attrib::Enum" + +func.VertexDecl.skip + "void" + .num "uint8_t" + +-- Notice: `end` is a keyword in lua +func.VertexDecl["end"] + "void" + +func.vertexPack + "void" + .input "const float *" + .inputNormalized "bool" + .attr "Attrib::Enum" + .decl "const VertexDecl &" + .data "void *" + .index "uint32_t" + +func.vertexUnpack + "void" + .output "float *" { out } + .attr "Attrib::Enum" + .decl "const VertexDecl &" + .data "const void *" + .index "uint32_t" + +func.vertexConvert + "void" + .dstDecl "const VertexDecl &" + .dstData "void *" + .srcDecl "const VertexDecl &" + .srcData "const void *" + .num "uint32_t" + +func.weldVertices + "uint16_t" + .output "uint16_t *" + .decl "const VertexDecl &" + .data "const void *" + .num "uint16_t" + .epsilon "float" + +func.topologyConvert + "uint32_t" + .conversion "TopologyConvert::Enum" + .dst "void *" { out } + .dstSize "uint32_t" + .indices "const void *" + .numIndices "uint32_t" + .index32 "bool" + +func.topologySortTriList + "void" + .sort "TopologySort::Enum" + .dst "void *" { out } + .dstSize "uint32_t" + .dir "const float *" + .pos "const float *" + .vertices "const void *" + .stride "uint32_t" + .indices "const void *" + .numIndices "uint32_t" + .index32 "bool" + +func.getSupportedRenderers + "uint8_t" + .max "uint8_t" + .enum "RendererType::Enum *" { out } + +func.getRendererName + "const char *" + .type "RendererType::Enum" + +local init_ctor = [[ + BX_PLACEMENT_NEW(_init, bgfx::Init); +]] +func.initCtor { cfunc = init_ctor } + "void" + .init "Init *" + +local init = [[ + bgfx_init_t init = *_init; + + if (init.callback != NULL) + { + static bgfx::CallbackC99 s_callback; + s_callback.m_interface = init.callback; + init.callback = reinterpret_cast(&s_callback); + } + + if (init.allocator != NULL) + { + static bgfx::AllocatorC99 s_allocator; + s_allocator.m_interface = init.allocator; + init.allocator = reinterpret_cast(&s_allocator); + } + + union { const bgfx_init_t* c; const bgfx::Init* cpp; } in; + in.c = &init; + + return bgfx::init(*in.cpp); +]] +func.init { cfunc = init } + "bool" + .init "const Init &" + +func.shutdown + "void" + +func.reset + "void" + .width "uint32_t" + .height "uint32_t" + .flags "uint32_t" + .format "TextureFormat::Enum" + +func.frame + "uint32_t" + .capture "bool" + +func.getRendererType + "RendererType::Enum" + +func.getCaps + "const Caps *" + +func.getStats + "const Stats *" + +func.alloc + "const Memory *" + .size "uint32_t" + +func.copy + "const Memory *" + .data "const void *" + .size "uint32_t" + +func.makeRef + "const Memory *" + .data "const void *" + .size "uint32_t" + +func.makeRef { cname = "make_ref_release" } + "const Memory *" + .data "const void *" + .size "uint32_t" + .releaseFn "ReleaseFn" + .userData "void *" + +func.setDebug + "void" + .debug "uint32_t" + +func.dbgTextClear + "void" + .attr "uint8_t" + .small "bool" + +func.dbgTextPrintf { vararg = "dbgTextPrintfVargs" } + "void" + .x "uint16_t" + .y "uint16_t" + .attr "uint8_t" + .format "const char *" + +func.dbgTextPrintfVargs { cname = "dbg_text_vprintf" } + "void" + .x "uint16_t" + .y "uint16_t" + .attr "uint8_t" + .format "const char *" + .argList "va_list" + +func.dbgTextImage + "void" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + .data "const void *" + .pitch "uint16_t" + +func.createIndexBuffer + "IndexBufferHandle" + .mem "const Memory *" + .flags "uint16_t" + +func.setName { cname = "set_index_buffer_name" } + "void" + .handle "IndexBufferHandle" + .name "const char *" + .len "int32_t" + +func.destroy { cname = "destroy_index_buffer" } + "void" + .handle "IndexBufferHandle" + +func.createVertexBuffer + "VertexBufferHandle" + .mem "const Memory *" + .decl "const VertexDecl &" + .flags "uint16_t" + +func.setName { cname = "set_vertex_buffer_name" } + "void" + .handle "VertexBufferHandle" + .name "const char *" + .len "int32_t" + +func.destroy { cname = "destroy_vertex_buffer" } + "void" + .handle "VertexBufferHandle" + +func.createDynamicIndexBuffer + "DynamicIndexBufferHandle" + .num "uint32_t" + .flags "uint16_t" + +func.createDynamicIndexBuffer { cname = "create_dynamic_index_buffer_mem" } + "DynamicIndexBufferHandle" + .mem "const Memory *" + .flags "uint16_t" + +func.update { cname = "update_dynamic_index_buffer" } + "void" + .handle "DynamicIndexBufferHandle" + .startIndex "uint32_t" + .mem "const Memory *" + +func.destroy { cname = "destroy_dynamic_index_buffer" } + "void" + .handle "DynamicIndexBufferHandle" + +func.createDynamicVertexBuffer + "DynamicVertexBufferHandle" + .num "uint32_t" + .decl "const VertexDecl &" + .flags "uint16_t" + +func.createDynamicVertexBuffer { cname = "create_dynamic_vertex_buffer_mem" } + "DynamicVertexBufferHandle" + .mem "const Memory *" + .decl "const VertexDecl &" + .flags "uint16_t" + +func.update { cname = "update_dynamic_vertex_buffer" } + "void" + .handle "DynamicVertexBufferHandle" + .startVertex "uint32_t" + .mem "const Memory *" + +func.destroy { cname = "destroy_dynamic_vertex_buffer" } + "void" + .handle "DynamicVertexBufferHandle" + +func.getAvailTransientIndexBuffer + "uint32_t" + .num "uint32_t" + +func.getAvailTransientVertexBuffer + "uint32_t" + .num "uint32_t" + .decl "const VertexDecl &" + +func.getAvailInstanceDataBuffer + "uint32_t" + .num "uint32_t" + .stride "uint16_t" + +func.allocTransientIndexBuffer + "void" + .tib "TransientIndexBuffer *" { out } + .num "uint32_t" + +func.allocTransientVertexBuffer + "void" + .tvb "TransientVertexBuffer *" { out } + .num "uint32_t" + .decl "const VertexDecl &" + +func.allocTransientBuffers + "bool" + .tvb "TransientVertexBuffer *" { out } + .decl "const VertexDecl &" + .numVertices "uint32_t" + .tib "TransientIndexBuffer *" { out } + .numIndices "uint32_t" + +func.allocInstanceDataBuffer + "void" + .idb "InstanceDataBuffer *" { out } + .num "uint32_t" + .stride "uint16_t" + +func.createIndirectBuffer + "IndirectBufferHandle" + .num "uint32_t" + +func.destroy { cname = "destroy_indirect_buffer" } + "void" + .handle "IndirectBufferHandle" + +func.createShader + "ShaderHandle" + .mem "const Memory *" + +func.getShaderUniforms + "uint16_t" + .handle "ShaderHandle" + .uniforms "UniformHandle *" { out } + .max "uint16_t" + +func.setName { cname = "set_shader_name" } + "void" + .handle "ShaderHandle" + .name "const char *" + .len "int32_t" + +func.destroy { cname = "destroy_shader" } + "void" + .handle "ShaderHandle" + +func.createProgram + "ProgramHandle" + .vsh "ShaderHandle" + .fsh "ShaderHandle" + .destroyShaders "bool" + +func.createProgram { cname = "create_compute_program" } + "ProgramHandle" + .csh "ShaderHandle" + .destroyShaders "bool" + +func.destroy { cname = "destroy_program" } + "void" + .handle "ProgramHandle" + +func.isTextureValid + "bool" + .depth "uint16_t" + .cubeMap "bool" + .numLayers "uint16_t" + .format "TextureFormat::Enum" + .flags "uint64_t" + +func.calcTextureSize + "void" + .info "TextureInfo &" { out } + .width "uint16_t" + .height "uint16_t" + .depth "uint16_t" + .cubeMap "bool" + .hasMips "bool" + .numLayers "uint16_t" + .format "TextureFormat::Enum" + +func.createTexture + "TextureHandle" + .mem "const Memory *" + .flags "uint64_t" + .skip "uint8_t" + .info "TextureInfo *" { out } + +func.createTexture2D + "TextureHandle" + .width "uint16_t" + .height "uint16_t" + .hasMips "bool" + .numLayers "uint16_t" + .format "TextureFormat::Enum" + .flags "uint64_t" + .mem "const Memory *" + +func.createTexture2D { cname = "create_texture_2d_scaled" } + "TextureHandle" + .ratio "BackbufferRatio::Enum" + .hasMips "bool" + .numLayers "uint16_t" + .format "TextureFormat::Enum" + .flags "uint64_t" + +func.createTexture3D + "TextureHandle" + .width "uint16_t" + .height "uint16_t" + .depth "uint16_t" + .hasMips "bool" + .format "TextureFormat::Enum" + .flags "uint64_t" + .mem "const Memory *" + +func.createTextureCube + "TextureHandle" + .size "uint16_t" + .hasMips "bool" + .numLayers "uint16_t" + .format "TextureFormat::Enum" + .flags "uint64_t" + .mem "const Memory *" + +func.updateTexture2D + "void" + .handle "TextureHandle" + .layer "uint16_t" + .mip "uint16_t" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + .mem "const Memory *" + .pitch "uint16_t" + +func.updateTexture3D + "void" + .handle "TextureHandle" + .mip "uint16_t" + .x "uint16_t" + .y "uint16_t" + .z "uint16_t" + .width "uint16_t" + .height "uint16_t" + .depth "uint16_t" + .mem "const Memory *" + +func.updateTextureCube + "void" + .handle "TextureHandle" + .layer "uint16_t" + .side "uint8_t" + .mip "uint8_t" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + .mem "const Memory *" + .pitch "uint16_t" + +func.readTexture + "uint32_t" + .handle "TextureHandle" + .data "void *" + .mip "uint8_t" + +func.setName { cname = "set_texture_name" } + "void" + .handle "TextureHandle" + .name "const char *" + .len "int32_t" + +func.getDirectAccessPtr + "void *" + .handle "TextureHandle" + +func.destroy { cname = "destroy_texture" } + "void" + .handle "TextureHandle" + +func.createFrameBuffer + "FrameBufferHandle" + .width "uint16_t" + .height "uint16_t" + .format "TextureFormat::Enum" + .textureFlags "uint64_t" + +func.createFrameBuffer { cname = "create_frame_buffer_scaled" } + "FrameBufferHandle" + .ratio "BackbufferRatio::Enum" + .format "TextureFormat::Enum" + .textureFlags "uint64_t" + +func.createFrameBuffer { cname = "create_frame_buffer_from_handles" } + "FrameBufferHandle" + .num "uint8_t" + .handles "const TextureHandle *" + .destroyTexture "bool" + +func.createFrameBuffer { cname = "create_frame_buffer_from_attachment" } + "FrameBufferHandle" + .num "uint8_t" + .handles "const Attachment *" + .destroyTexture "bool" + +func.createFrameBuffer { cname = "create_frame_buffer_from_nwh" } + "FrameBufferHandle" + .nwh "void *" + .width "uint16_t" + .height "uint16_t" + .format "TextureFormat::Enum" + .depthFormat "TextureFormat::Enum" + +func.setName { cname = "set_frame_buffer_name" } + "void" + .handle "FrameBufferHandle" + .name "const char *" + .len "int32_t" + +func.getTexture + "TextureHandle" + .handle "FrameBufferHandle" + .attachment "uint8_t" + +func.destroy { cname = "destroy_frame_buffer" } + "void" + .handle "FrameBufferHandle" + +func.createUniform + "UniformHandle" + .name "const char *" + .type "UniformType::Enum" + .num "uint16_t" + +func.getUniformInfo + "void" + .handle "UniformHandle" + .info "UniformInfo &" { out } + +func.destroy { cname = "destroy_uniform" } + "void" + .handle "UniformHandle" + +func.createOcclusionQuery + "OcclusionQueryHandle" + +func.getResult + "OcclusionQueryResult::Enum" + .handle "OcclusionQueryHandle" + .result "int32_t *" { out } + +func.destroy { cname = "destroy_occlusion_query" } + "void" + .handle "OcclusionQueryHandle" + +func.setPaletteColor + "void" + .index "uint8_t" + .rgba "const float *" + +func.setViewName + "void" + .id "ViewId" + .name "const char *" + +func.setViewRect + "void" + .id "ViewId" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + +func.setViewRect { cname = "set_view_rect_ratio" } + "void" + .id "ViewId" + .x "uint16_t" + .y "uint16_t" + .ratio "BackbufferRatio::Enum" + +func.setViewScissor + "void" + .id "ViewId" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + +func.setViewClear + "void" + .id "ViewId" + .flags "uint16_t" + .rgba "uint32_t" + .depth "float" + .stencil "uint8_t" + +func.setViewClear { cname = "set_view_clear_mrt" } + "void" + .id "ViewId" + .flags "uint16_t" + .depth "float" + .stencil "uint8_t" + .c0 "uint8_t" + .c1 "uint8_t" + .c2 "uint8_t" + .c3 "uint8_t" + .c4 "uint8_t" + .c5 "uint8_t" + .c6 "uint8_t" + .c7 "uint8_t" + +func.setViewMode + "void" + .id "ViewId" + .mode "ViewMode::Enum" + +func.setViewFrameBuffer + "void" + .id "ViewId" + .handle "FrameBufferHandle" + +func.setViewTransform + "void" + .id "ViewId" + .view "const void *" + .proj "const void *" + +func.setViewOrder + "void" + .id "ViewId" + .num "uint16_t" + .order "const ViewId *" + +func.begin { cname = "encoder_begin" } + "Encoder *" + .forThread "bool" + +func["end"] { cname = "encoder_end" } + "void" + .encoder "Encoder *" + +func.Encoder.setMarker + "void" + .marker "const char *" + +func.Encoder.setState + "void" + .state "uint64_t" + .rgba "uint32_t" + +func.Encoder.setCondition + "void" + .handle "OcclusionQueryHandle" + .visible "bool" + +func.Encoder.setStencil + "void" + .fstencil "uint32_t" + .bstencil "uint32_t" + +func.Encoder.setScissor + "uint16_t" + .x "uint16_t" + .y "uint16_t" + .width "uint16_t" + .height "uint16_t" + +func.Encoder.setScissor { cname = "set_scissor_cached" } + "void" + .cache "uint16_t" + +func.Encoder.setTransform + "uint32_t" + .mtx "const void *" + .num "uint16_t" + +func.Encoder.setTransform { cname = "set_transform_cached" } + "void" + .cache "uint32_t" + .num "uint16_t" + +func.Encoder.allocTransform + "uint32_t" + .transform "Transform *" { out } + .num "uint16_t" + +func.Encoder.setUniform + "void" + .handle "UniformHandle" + .value "const void *" + .num "uint16_t" + +func.Encoder.setIndexBuffer + "void" + .handle "IndexBufferHandle" + .firstIndex "uint32_t" + .numIndices "uint32_t" + +func.Encoder.setIndexBuffer { cname = "set_dynamic_index_buffer" } + "void" + .handle "DynamicIndexBufferHandle" + .firstIndex "uint32_t" + .numIndices "uint32_t" + +func.Encoder.setIndexBuffer { cname = "set_transient_index_buffer" } + "void" + .tib "const TransientIndexBuffer *" + .firstIndex "uint32_t" + .numIndices "uint32_t" + +func.Encoder.setVertexBuffer + "void" + .stream "uint8_t" + .handle "VertexBufferHandle" + .startVertex "uint32_t" + .numVertices "uint32_t" + +func.Encoder.setVertexBuffer { cname = "set_dynamic_vertex_buffer" } + "void" + .stream "uint8_t" + .handle "DynamicVertexBufferHandle" + .startVertex "uint32_t" + .numVertices "uint32_t" + +func.Encoder.setVertexBuffer { cname = "set_transient_vertex_buffer" } + "void" + .stream "uint8_t" + .tvb "const TransientVertexBuffer *" + .startVertex "uint32_t" + .numVertices "uint32_t" + +func.Encoder.setVertexCount + "void" + .numVertices "uint32_t" + +func.Encoder.setInstanceDataBuffer + "void" + .idb "const InstanceDataBuffer *" + .start "uint32_t" + .num "uint32_t" + +func.Encoder.setInstanceDataBuffer { cname = "set_instance_data_from_vertex_buffer" } + "void" + .handle "VertexBufferHandle" + .startVertex "uint32_t" + .num "uint32_t" + +func.Encoder.setInstanceDataBuffer { cname = "set_instance_data_from_dynamic_vertex_buffer" } + "void" + .handle "DynamicVertexBufferHandle" + .startVertex "uint32_t" + .num "uint32_t" + +func.Encoder.setInstanceCount + "void" + .numInstances "uint32_t" + +func.Encoder.setTexture + "void" + .stage "uint8_t" + .sampler "UniformHandle" + .handle "TextureHandle" + .flags "uint32_t" + +func.Encoder.touch + "void" + .id "ViewId" + +func.Encoder.submit + "void" + .id "ViewId" + .program "ProgramHandle" + .depth "uint32_t" + .preserveState "bool" + +func.Encoder.submit { cname = "submit_occlusion_query" } + "void" + .id "ViewId" + .program "ProgramHandle" + .occlusionQuery "OcclusionQueryHandle" + .depth "uint32_t" + .preserveState "bool" + +func.Encoder.submit { cname = "submit_indirect" } + "void" + .id "ViewId" + .program "ProgramHandle" + .indirectHandle "IndirectBufferHandle" + .start "uint16_t" + .num "uint16_t" + .depth "uint32_t" + .preserveState "bool" + +func.Encoder.setBuffer { cname = "set_compute_index_buffer" } + "void" + .stage "uint8_t" + .handle "IndexBufferHandle" + .access "Access::Enum" + +func.Encoder.setBuffer { cname = "set_compute_vertex_buffer" } + "void" + .stage "uint8_t" + .handle "VertexBufferHandle" + .access "Access::Enum" + +func.Encoder.setBuffer { cname = "set_compute_dynamic_index_buffer" } + "void" + .stage "uint8_t" + .handle "DynamicIndexBufferHandle" + .access "Access::Enum" + +func.Encoder.setBuffer { cname = "set_compute_dynamic_vertex_buffer" } + "void" + .stage "uint8_t" + .handle "DynamicVertexBufferHandle" + .access "Access::Enum" + +func.Encoder.setBuffer { cname = "set_compute_indirect_buffer" } + "void" + .stage "uint8_t" + .handle "IndirectBufferHandle" + .access "Access::Enum" + +func.Encoder.setImage + "void" + .stage "uint8_t" + .handle "TextureHandle" + .mip "uint8_t" + .access "Access::Enum" + .format "TextureFormat::Enum" + +func.Encoder.dispatch + "void" + .id "ViewId" + .program "ProgramHandle" + .numX "uint32_t" + .numY "uint32_t" + .numZ "uint32_t" + +func.Encoder.dispatch { cname = "dispatch_indirect" } + "void" + .id "ViewId" + .program "ProgramHandle" + .indirectHandle "IndirectBufferHandle" + .start "uint16_t" + .num "uint16_t" + +func.Encoder.discard + "void" + +func.Encoder.blit + "void" + .id "ViewId" + .dst "TextureHandle" + .dstMip "uint8_t" + .dstX "uint16_t" + .dstY "uint16_t" + .dstZ "uint16_t" + .src "TextureHandle" + .srcMip "uint8_t" + .srcX "uint16_t" + .srcY "uint16_t" + .srcZ "uint16_t" + .width "uint16_t" + .height "uint16_t" + .depth "uint16_t" + +func.requestScreenShot + "void" + .handle "FrameBufferHandle" + .filePath "const char *" + +func.renderFrame + "RenderFrame::Enum" + .msecs "int32_t" + +func.setPlatformData + "void" + .data "const PlatformData &" + +func.getInternalData + "const InternalData *" + +func.overrideInternal { cname = "override_internal_texture_ptr" } + "uintptr_t" + .handle "TextureHandle" + .ptr "uintptr_t" + +func.overrideInternal { cname = "override_internal_texture" } + "uintptr_t" + .handle "TextureHandle" + .width "uint16_t" + .height "uint16_t" + .numMips "uint8_t" + .format "TextureFormat::Enum" + .flags "uint32_t" diff --git a/scripts/codegen.lua b/scripts/codegen.lua new file mode 100644 index 000000000..c72e06e48 --- /dev/null +++ b/scripts/codegen.lua @@ -0,0 +1,271 @@ +-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved. +-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE + +local codegen = {} + +local function camelcase_to_underscorecase(name) + local tmp = {} + for v in name:gmatch "[%u%d]+%l*" do + tmp[#tmp+1] = v:lower() + end + return table.concat(tmp, "_") +end + +local function convert_typename(name) + if name:match "^%u" then + return "bgfx_" .. camelcase_to_underscorecase(name) .. "_t" + else + return name + end +end + +local function convert_funcname(name) + name = name:gsub("^%l", string.upper) -- Change to upper CamlCase + return camelcase_to_underscorecase(name) +end + +local function convert_arg(all_types, arg, what) + local t, postfix = arg.fulltype:match "(%a[%a%d_:]*)%s*([*&]+)%s*$" + if t then + arg.type = t + if postfix == "&" then + arg.ref = true + end + else + arg.type = arg.fulltype + end + local ctype = all_types[arg.type] + if not ctype then + error ("Undefined type " .. arg.fulltype .. " for " .. what) + end + arg.ctype = arg.fulltype:gsub(arg.type, ctype.cname):gsub("&", "*") + if ctype.cname ~= arg.type then + arg.cpptype = arg.fulltype:gsub(arg.type, "bgfx::"..arg.type) + else + arg.cpptype = arg.fulltype + end + if arg.ref then + arg.ptype = arg.cpptype:gsub("&", "*") + end +end + +local function alternative_name(name) + if name:sub(1,1) == "_" then + return name:sub(2) + else + return name .. "_" + end +end + +local function gen_arg_conversion(all_types, arg) + if arg.ctype == arg.fulltype then + -- do not need conversion + arg.aname = arg.name + return + end + local ctype = all_types[arg.type] + if ctype.handle and arg.type == arg.fulltype then + local aname = alternative_name(arg.name) + arg.aname = aname .. ".cpp" + arg.conversion = string.format( + "union { %s c; bgfx::%s cpp; } %s = { %s };" , + ctype.cname, arg.type, aname, arg.name) + elseif arg.ref then + if ctype.cname == arg.type then + arg.aname = "*" .. arg.name + elseif arg.out and ctype.enum then + local aname = alternative_name(arg.name) + local cpptype = arg.cpptype:match "(.-)%s*&" -- remove & + arg.aname = aname + arg.conversion = string.format("%s %s;", cpptype, aname) + arg.out_conversion = string.format("*%s = (%s)%s;", arg.name, ctype.cname, aname) + else + arg.aname = alternative_name(arg.name) + arg.conversion = string.format( + "%s %s = *(%s)%s;", + arg.cpptype, arg.aname, arg.ptype, arg.name) + end + else + arg.aname = string.format( + "(%s)%s", + arg.cpptype, arg.name) + end +end + +local function gen_ret_conversion(all_types, func) + local postfix = { func.vararg and "va_end(argList);" } + func.ret_postfix = postfix + + for _, arg in ipairs(func.args) do + if arg.out_conversion then + postfix[#postfix+1] = arg.out_conversion + end + end + + local ctype = all_types[func.ret.type] + if ctype.handle then + func.ret_conversion = string.format( + "union { %s c; bgfx::%s cpp; } handle_ret;" , + ctype.cname, func.ret.type) + func.ret_prefix = "handle_ret.cpp = " + postfix[#postfix+1] = "return handle_ret.c;" + elseif func.ret.fulltype ~= "void" then + local ctype_conversion = func.ret.type == func.ret.ctype and "" or ("(" .. func.ret.ctype .. ")") + if #postfix > 0 then + func.ret_prefix = string.format("%s retValue = %s", func.ret.ctype , ctype_conversion) + postfix[#postfix+1] = "return retValue;" + else + func.ret_prefix = string.format("return %s", ctype_conversion) + end + end +end + +function codegen.nameconversion(all_types, all_funcs) + local enums = {} + for k,v in pairs(all_types) do + if not v.cname then + v.cname = convert_typename(k) + end + if v.enum then + enums[#enums+1] = k + end + end + for _, e in ipairs(enums) do + local t = all_types[e] + all_types[e] = nil + all_types[e .. "::Enum"] = t + end + + for _,v in ipairs(all_funcs) do + if v.cname == nil then + v.cname = convert_funcname(v.name) + end + if v.class then + v.cname = convert_funcname(v.class) .. "_" .. v.cname + end + for _, arg in ipairs(v.args) do + convert_arg(all_types, arg, v.name) + gen_arg_conversion(all_types, arg) + end + if v.vararg then + local args = v.args + local vararg = { + name = "", + ctype = "...", + aname = "argList", + conversion = string.format( + "va_list argList;\n\tva_start(argList, %s);", + args[#args].name), + } + args[#args + 1] = vararg + v.implname = v.vararg + else + v.implname = v.name + end + convert_arg(all_types, v.ret, v.name .. "@rettype") + gen_ret_conversion(all_types, v) + if v.class then + local classname = v.class + if v.const then + classname = "const " .. classname + end + local classtype = { fulltype = classname .. "*" } + convert_arg(all_types, classtype, "class member " .. v.name) + v.this = classtype.ctype .. " _this" + v.this_conversion = string.format( "%s This = (%s)_this;", classtype.cpptype, classtype.cpptype) + end + end +end + +local function lines(tbl) + if #tbl == 0 then + return "//EMPTYLINE" + else + return table.concat(tbl, "\n\t") + end +end + +local function remove_emptylines(txt) + return (txt:gsub("\t//EMPTYLINE\n", "")) +end + +local function codetemp(func) + local conversion = {} + local args = {} + local callargs = {} + local cppfunc + if func.class then + -- It's a member function + args[1] = func.this + conversion[1] = func.this_conversion + cppfunc = "This->" .. func.name + else + cppfunc = "bgfx::" .. func.implname + end + for _, arg in ipairs(func.args) do + conversion[#conversion+1] = arg.conversion + args[#args+1] = arg.ctype .. " " .. arg.name + callargs[#callargs+1] = arg.aname + end + conversion[#conversion+1] = func.ret_conversion + + return { + RET = func.ret.ctype, + FUNCNAME = func.cname, + ARGS = table.concat(args, ", "), + CONVERSION = lines(conversion), + PRERET = func.ret_prefix or "", + CPPFUNC = cppfunc, + CALLARGS = table.concat(callargs, ", "), + POSTRET = lines(func.ret_postfix), + CODE = func.cfunc, + } +end + +local function apply_template(func, temp) + func.codetemp = func.codetemp or codetemp(func) + return (temp:gsub("$(%u+)", func.codetemp)) +end + +local c99temp = [[ +BGFX_C_API $RET bgfx_$FUNCNAME($ARGS) +{ + $CONVERSION + $PRERET$CPPFUNC($CALLARGS); + $POSTRET +} +]] + +local c99usertemp = [[ +BGFX_C_API $RET bgfx_$FUNCNAME($ARGS) +{ +$CODE +} +]] + +function codegen.gen_c99(func) + if func.cfunc then + return apply_template(func, c99usertemp) + else + return remove_emptylines(apply_template(func, c99temp)) + end +end + +local template_function_declaration = [[ +/**/ +BGFX_C_API $RET bgfx_$FUNCNAME($ARGS); +]] + +function codegen.gen_c99decl(func) + return apply_template(func, template_function_declaration) +end + +function codegen.gen_interface_struct(func) + return apply_template(func, "$RET (*$FUNCNAME)($ARGS);") +end + +function codegen.gen_interface_import(func) + return "bgfx_" .. func.cname +end + +return codegen diff --git a/scripts/genie.lua b/scripts/genie.lua index 11d390a8d..1405f2924 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -48,6 +48,14 @@ newoption { description = "Enable building examples.", } +dofile "bgfx-idl.lua" + +newaction { + trigger = "idl", + description = "Generate bgfx interface source code", + execute = doidl +} + solution "bgfx" configurations { "Debug", diff --git a/scripts/idl.lua b/scripts/idl.lua new file mode 100644 index 000000000..200821a18 --- /dev/null +++ b/scripts/idl.lua @@ -0,0 +1,105 @@ +-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved. +-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE + +local idl = {} + +local all_types = {} + +local function typedef(_, typename) + assert(all_types[typename] == nil, "Duplicate type") + local t = {} + all_types[typename] = t + local function type_attrib(attrib) + assert(type(attrib) == "table", "type attrib should be a table") + for _, a in ipairs(attrib) do + t[a] = true + end + end + return function(cname) + local typ = type(cname) + if typ == "table" then + type_attrib(cname) + return + end + assert(typ == "string" , "type should be a string") + t.cname = cname + return type_attrib + end +end + +idl.typedef = setmetatable({} , { __index = typedef, __call = typedef }) +idl.types = all_types + +local all_funcs = {} + +local function duplicate_arg_name(name) + error ("Duplicate arg name " .. name) +end + +local function funcdef(_, funcname) + local f = { name = funcname , args = {} } + all_funcs[#all_funcs+1] = f + local args + local function args_desc(obj, args_name) + obj[args_name] = duplicate_arg_name + return function (fulltype) + local arg = { + name = "_" .. args_name, + fulltype = fulltype, + } + f.args[#f.args+1] = arg + local function arg_attrib(_, attrib ) + assert(type(attrib) == "table", "Arg attributes should be a table") + for _, a in ipairs(attrib) do + arg[a] = true + end + return args + end + return setmetatable( {} , { + __index = function(_, name) + return args_desc(obj, name) + end + , __call = arg_attrib } ) + end + end + args = setmetatable({}, { __index = args_desc }) + local function rettype(value) + assert(type(value) == "string", "Need return type") + f.ret = { fulltype = value } + return args + end + + local function funcdef(value) + if type(value) == "table" then + for k,v in pairs(value) do + if type(k) == "number" then + f[v] = true + else + f[k] = v + end + end + return rettype + end + return rettype(value) + end + + local function classfunc(_, methodname) + f.class = f.name + f.name = methodname + return funcdef + end + + return setmetatable({} , { __index = classfunc, __call = function(_, value) return funcdef(value) end }) +end + +idl.func = setmetatable({}, { __index = funcdef }) +idl.funcs = all_funcs + +idl.handle = "handle" +idl.enum = "enum" +idl.out = "out" +idl.const = "const" + +return setmetatable(idl , { __index = function (_, keyword) + error (tostring(keyword) .. " is invalid") + end})