From f3c88af7e5db334fbce6cc4399e6b7e41dc33812 Mon Sep 17 00:00:00 2001 From: pixel Date: Tue, 5 Aug 2008 15:03:30 +0000 Subject: Adding the luaosmesa plugin. --- src/plugin-luaosmesa.cc | 254 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 src/plugin-luaosmesa.cc (limited to 'src') diff --git a/src/plugin-luaosmesa.cc b/src/plugin-luaosmesa.cc new file mode 100644 index 0000000..830c2db --- /dev/null +++ b/src/plugin-luaosmesa.cc @@ -0,0 +1,254 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#ifndef WIN32 +#define WEAK __attribute__ ((weak)) +#else +#define WEAK +#endif + +OSMesaContext ctx = 0; +void *buffer = 0; +int width = -1; +int height = -1; +bool upscale = false; + +class scene_t : public Base { + public: + std::list scene; + String filename, tmp_filename; +};void empty_scene(scene_t scene) { + while (scene.scene.begin() != scene.scene.end()) { + scene.scene.pop_front(); + } +} + +scene_t * init_OSMesa_context(scene_t * scene, int _width, int _height) { + scene_t * r = scene; + + if ((width > 2048) || (height > 2048)) { + printf("Image too wide!\n"); + return NULL; + } + + if (!r) + r = new scene_t(); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + + if ((width == _width) && (height == _height)) { + return r; + } + + width = _width; + height = _height; + + /* Bind the buffer to the context and make it current */ + if (!OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, width, height)) { + printf("OSMesaMakeCurrent (8 bits/channel) failed!\n"); + delete r; + return NULL; + } + return r; +} + +void init_OSMesa() { + const GLint z = 32, stencil = 0, accum = 0; + + ctx = OSMesaCreateContextExt(OSMESA_BGRA, z, stencil, accum, NULL); + if (!ctx) { + printf("OSMesaCreateContextExt() failed!\n"); + return; + } + + buffer = malloc(2048 * 2048 * 4); + + if (!buffer) { + printf("Alloc image buffer failed!\n"); + return; + } + + delete init_OSMesa_context(0, 300, 300); + glPopAttrib(); +} + +void flip_scene(scene_t * scene, const char * buffer, int width, int height, bool upscale) { + /* Make sure buffered commands are finished! */ + glFinish(); + + Magick::Image i(width, height, "BGRA", Magick::CharPixel, buffer); + i.flip(); + i.animationDelay(6); + i.opacity(0); + + if (upscale) { + i.resize(Magick::Geometry(width / 2, height / 2)); + } + + scene->scene.push_back(i); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void * dump_scene_threaded(void * arg) { + scene_t * scene = (scene_t *) arg; + char fname[2049]; + + writeImages(scene->scene.begin(), scene->scene.end(), scene->tmp_filename.to_charp()); + unlink(scene->filename.to_charp()); + rename(scene->tmp_filename.to_charp(), scene->filename.to_charp()); + delete scene; + pthread_exit(0); +} + +void dump_scene(scene_t * scene, const String & filename, Handle * out, const char * buffer, int width, int height, bool upscale) { + if (scene->scene.begin() == scene->scene.end()) + flip_scene(scene, buffer, width, height, upscale); + + if (out) { + Magick::Blob b; + scene->scene.begin()->magick("JPEG"); + scene->scene.begin()->quality(95); + writeImages(scene->scene.begin(), scene->scene.end(), &b); + out->write(b.data(), b.length()); + delete scene; + } else { + pthread_t thread; + scene->filename = filename; + scene->tmp_filename = "tmp-" + filename; + if (pthread_create(&thread, NULL, dump_scene_threaded, scene) == 0) { + pthread_detach(thread); + } + } + + glPopAttrib(); + + return; +} + +class plugin_osmesa : public Base { +}; + +class Luaplugin_osmesa : public LuaObject { + public: + static void pushstatics(Lua *) throw (GeneralException); + protected: + virtual void pushmembers(Lua *); +}; + +enum plugin_osmesa_functions_t { + PLUGIN_OSMESA_INITOSMESA, + PLUGIN_OSMESA_FLIPSCENE, + PLUGIN_OSMESA_DUMPSCENE, + PLUGIN_OSMESA_LOADTEX, +}; + +struct lua_functypes_t plugin_osmesa_functions[] = { + { PLUGIN_OSMESA_INITOSMESA, "InitOSMesa", 3, 4, { BLUA_USERDATA | BLUA_NIL, BLUA_NUMBER, BLUA_NUMBER, BLUA_BOOLEAN } }, + { PLUGIN_OSMESA_FLIPSCENE, "FlipScene", 1, 1, { BLUA_USERDATA } }, + { PLUGIN_OSMESA_DUMPSCENE, "DumpScene", 2, 2, { BLUA_USERDATA, BLUA_STRING | BLUA_OBJECT } }, + { PLUGIN_OSMESA_LOADTEX, "LoadTex", 1, 1, { BLUA_STRING } }, + { -1, 0, 0, 0, 0 } +}; + +class sLua_plugin_osmesa : public Base { + public: + DECLARE_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_INITOSMESA); + DECLARE_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_FLIPSCENE); + DECLARE_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_DUMPSCENE); + DECLARE_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_LOADTEX); + private: + static int plugin_osmesa_proceed(Lua * L, int n, plugin_osmesa * obj, int caller); + static int plugin_osmesa_proceed_statics(Lua * L, int n, int caller); +}; +void Luaplugin_osmesa::pushmembers(Lua * L) { } + +void Luaplugin_osmesa::pushstatics(Lua * L) throw (GeneralException) { + //CHECK_METHODS(plugin_osmesa); + CHECK_FUNCTIONS(plugin_osmesa); + + PUSH_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_INITOSMESA); + PUSH_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_FLIPSCENE); + PUSH_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_DUMPSCENE); + PUSH_FUNCTION(plugin_osmesa, PLUGIN_OSMESA_LOADTEX); +} + +int sLua_plugin_osmesa::plugin_osmesa_proceed(Lua * L, int n, plugin_osmesa * obj, int caller) { + return 0; +} + +int sLua_plugin_osmesa::plugin_osmesa_proceed_statics(Lua * L, int n, int caller) { + int _width, _height, r = 0; + String filename; + const char * t; + DDS_IMAGE_DATA * dds; + scene_t * scene = 0; + + switch (caller) { + case PLUGIN_OSMESA_INITOSMESA: + if (!L->isnil(1)) { + scene = (scene_t *) L->touserdata(1); + } + _width = L->tonumber(2); + _height = L->tonumber(3); + if (n == 4) { + upscale = L->toboolean(4); + } else { + upscale = false; + } + L->push(init_OSMesa_context(scene, _width, _height)); + r = 1; + break; + case PLUGIN_OSMESA_FLIPSCENE: + flip_scene((scene_t *) L->touserdata(1), (char *) buffer, width, height, upscale); + break; + case PLUGIN_OSMESA_DUMPSCENE: + if (L->isstring(2)) { + filename = L->tostring(2); + dump_scene((scene_t *) L->touserdata(1), filename, 0, (char *) buffer, width, height, upscale); + } else { + Handle * t = (Handle *) LuaObject::getme(L, 2); + dump_scene((scene_t *) L->touserdata(1), "", t, (char *) buffer, width, height, upscale); + } + break; + case PLUGIN_OSMESA_LOADTEX: + filename = L->tostring(1); + t = filename.to_charp(); + dds = loadDDSTextureFile(t); + L->push((lua_Number) loadCompressedTexture(dds)); + L->push((lua_Number) dds->width); + L->push((lua_Number) dds->height); + destroyDDS(dds); + r = 3; + break; + } + + return r; +} + +static void _init_plugin(Lua * L) { + init_OSMesa(); + Luaplugin_osmesa::pushstatics(L); +} + +extern "C" { + +WEAK void init_plugin(Lua * L) { + _init_plugin(L); +} + +void luaosmesa_init(Lua * L) { + _init_plugin(L); +} + +} -- cgit v1.2.3