Merged in fbos

This commit is contained in:
Bart van Strien
2010-09-04 16:53:19 +02:00
13 changed files with 670 additions and 119 deletions
+4
View File
@@ -7,6 +7,10 @@ glob:extra/reshax/Debug/
glob:extra/reshax/resources.h
glob:extra/reshax/resources.cpp
glob:*.obj
glob:*.o
glob:*.dirstamp
glob:*.m4
glob:*.Po
glob:*.dll
glob:*.user
glob:*.suo
@@ -187,6 +187,8 @@
A98D914410507C97008E03F2 /* EncodedImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A98D914310507C97008E03F2 /* EncodedImageData.cpp */; };
A9B4BA9C1045937F001DBC80 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9B4BA9A1045937F001DBC80 /* ParticleSystem.cpp */; };
A9B4BA9D1045937F001DBC80 /* wrap_ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9B4BA9B1045937F001DBC80 /* wrap_ParticleSystem.cpp */; };
A9BD60741226C988007DEC63 /* Framebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BD60701226C988007DEC63 /* Framebuffer.cpp */; };
A9BD60751226C988007DEC63 /* wrap_Framebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9BD60721226C988007DEC63 /* wrap_Framebuffer.cpp */; };
A9CF0E8610B9EB1000E6F37E /* utf8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9CF0E8510B9EB1000E6F37E /* utf8.cpp */; };
A9D307EA106635C3004FEDF8 /* physfs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; };
A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; };
@@ -598,6 +600,10 @@
A9B4BA991045937F001DBC80 /* wrap_ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ParticleSystem.h; sourceTree = "<group>"; };
A9B4BA9A1045937F001DBC80 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; };
A9B4BA9B1045937F001DBC80 /* wrap_ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ParticleSystem.cpp; sourceTree = "<group>"; };
A9BD60701226C988007DEC63 /* Framebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Framebuffer.cpp; sourceTree = "<group>"; };
A9BD60711226C988007DEC63 /* Framebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Framebuffer.h; sourceTree = "<group>"; };
A9BD60721226C988007DEC63 /* wrap_Framebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Framebuffer.cpp; sourceTree = "<group>"; };
A9BD60731226C988007DEC63 /* wrap_Framebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Framebuffer.h; sourceTree = "<group>"; };
A9BFAA851137C1CE005FE0AD /* ThreadModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadModule.h; sourceTree = "<group>"; };
A9CF0E8410B9EB1000E6F37E /* utf8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utf8.h; sourceTree = "<group>"; };
A9CF0E8510B9EB1000E6F37E /* utf8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = utf8.cpp; sourceTree = "<group>"; };
@@ -985,6 +991,8 @@
children = (
A93E6A8710420AC2007D418B /* Font.cpp */,
A93E6A8810420AC2007D418B /* Font.h */,
A9BD60701226C988007DEC63 /* Framebuffer.cpp */,
A9BD60711226C988007DEC63 /* Framebuffer.h */,
A93E6A8910420AC2007D418B /* GLee.c */,
A93E6A8A10420AC2007D418B /* GLee.h */,
A93E6A8B10420AC2007D418B /* Glyph.cpp */,
@@ -1001,6 +1009,8 @@
A93E6A9610420AC2007D418B /* SpriteBatch.h */,
A93E6A9910420AC2007D418B /* wrap_Font.cpp */,
A93E6A9A10420AC2007D418B /* wrap_Font.h */,
A9BD60721226C988007DEC63 /* wrap_Framebuffer.cpp */,
A9BD60731226C988007DEC63 /* wrap_Framebuffer.h */,
A93E6A9B10420AC2007D418B /* wrap_Glyph.cpp */,
A93E6A9C10420AC2007D418B /* wrap_Glyph.h */,
A93E6A9D10420AC3007D418B /* wrap_Graphics.cpp */,
@@ -1660,6 +1670,8 @@
A946CE821172BCD7005E1462 /* wrap_EncodedImageData.cpp in Sources */,
A946D3BB117681BD005E1462 /* FontData.cpp in Sources */,
A946D3C611768D69005E1462 /* wrap_FontData.cpp in Sources */,
A9BD60741226C988007DEC63 /* Framebuffer.cpp in Sources */,
A9BD60751226C988007DEC63 /* wrap_Framebuffer.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+2
View File
@@ -52,6 +52,7 @@ namespace love
GRAPHICS_PARTICLE_SYSTEM_ID,
GRAPHICS_SPRITE_BATCH_ID,
GRAPHICS_VERTEX_BUFFER_ID,
GRAPHICS_FRAMEBUFFER_ID,
// Image
IMAGE_IMAGE_DATA_ID,
@@ -116,6 +117,7 @@ namespace love
const bits GRAPHICS_PARTICLE_SYSTEM_T = (bits(1) << GRAPHICS_PARTICLE_SYSTEM_ID) | GRAPHICS_DRAWABLE_T;
const bits GRAPHICS_SPRITE_BATCH_T = (bits(1) << GRAPHICS_SPRITE_BATCH_ID) | GRAPHICS_DRAWABLE_T;
const bits GRAPHICS_VERTEX_BUFFER_T = (bits(1) << GRAPHICS_VERTEX_BUFFER_ID) | GRAPHICS_DRAWABLE_T;
const bits GRAPHICS_FRAMEBUFFER_T = (bits(1) << GRAPHICS_FRAMEBUFFER_ID) | GRAPHICS_DRAWABLE_T;
// Image.
const bits IMAGE_IMAGE_DATA_T = (bits(1) << IMAGE_IMAGE_DATA_ID) | DATA_T;
+324
View File
@@ -0,0 +1,324 @@
#include "Framebuffer.h"
#include <common/Matrix.h>
#include <string.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
namespace {
// functions to get opengl capabilities at runtime
vector<string> tokenize(const string& str)
{
vector<string> tokens;
istringstream iss( str );
copy(istream_iterator<string>(iss), istream_iterator<string>(),
back_inserter< vector<string> >(tokens));
return tokens;
}
float getOpenGLVersionNumber()
{
vector<string> tokens = tokenize( (const char*)glGetString(GL_VERSION) );
stringstream toNumber( tokens.at(0) );
double version;
toNumber >> version;
return version;
}
bool hasFramebufferExtension()
{
vector<string> ext = tokenize( (const char*)glGetString(GL_EXTENSIONS) );
return find(ext.begin(), ext.end(), "GL_EXT_framebuffer_object") != ext.end();
}
// strategy for fbo creation, interchangable at runtime:
// none, opengl >= 3.0, extensions
struct FramebufferStrategy {
/// create a new framebuffer, depthbuffer and texture
/**
* @param[out] framebuffer Framebuffer name
* @param[out] depthbuffer Depthbuffer name
* @param[out] img Texture name
* @param[in] width Width of framebuffer
* @param[in] height Height of framebuffer
* @return Creation status
*/
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
{ return GL_FRAMEBUFFER_UNSUPPORTED; }
/// remove objects
/**
* @param[in] framebuffer Framebuffer name
* @param[in] depthbuffer Depthbuffer name
* @param[in] img Texture name
*/
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img) {}
virtual void bindFBO(GLuint framebuffer) {}
};
#ifdef GL_VERSION_3_0
struct FramebufferStrategyGL3 : public FramebufferStrategy {
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
{
// generate depth buffer
glGenRenderbuffers(1, &depthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// generate texture save target
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
// create framebuffer
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, img, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthbuffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
// unbind buffers and texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return status;
}
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
{
glDeleteTextures(1, &img);
glDeleteRenderbuffers(1, &depthbuffer);
glDeleteFramebuffers(1, &framebuffer);
}
virtual void bindFBO(GLuint framebuffer)
{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
};
#endif
struct FramebufferStrategyEXT : public FramebufferStrategy {
virtual GLenum createFBO(GLuint& framebuffer, GLuint& depthbuffer, GLuint& img, int width, int height)
{
// generate depth buffer
glGenRenderbuffersEXT(1, &depthbuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// generate texture save target
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
// create framebuffer
glGenFramebuffersEXT(1, &framebuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, img, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depthbuffer);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
// unbind buffers and texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return status;
}
virtual void deleteFBO(GLuint framebuffer, GLuint depthbuffer, GLuint img)
{
glDeleteTextures(1, &img);
glDeleteRenderbuffersEXT(1, &depthbuffer);
glDeleteFramebuffersEXT(1, &framebuffer);
}
virtual void bindFBO(GLuint framebuffer)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
}
};
FramebufferStrategy* strategy = NULL;
FramebufferStrategy strategyNone;
#ifdef GL_VERSION_3_0
FramebufferStrategyGL3 strategyGL3;
#endif
FramebufferStrategyEXT strategyEXT;
};
namespace love
{
namespace graphics
{
namespace opengl
{
Framebuffer* Framebuffer::current = NULL;
Framebuffer::Framebuffer(int width, int height) :
width(width), height(height)
{
// world coordinates
vertices[0].x = 0; vertices[0].y = 0;
vertices[1].x = 0; vertices[1].y = height;
vertices[2].x = width; vertices[2].y = height;
vertices[3].x = width; vertices[3].y = 0;
// texture coordinates
vertices[0].s = 0; vertices[0].t = 1;
vertices[1].s = 0; vertices[1].t = 0;
vertices[2].s = 1; vertices[2].t = 0;
vertices[3].s = 1; vertices[3].t = 1;
if (!strategy) {
#ifdef GL_VERSION_3_0
if (getOpenGLVersionNumber() >= 3.0)
strategy = &strategyGL3;
else if (hasFramebufferExtension())
#else
if (hasFramebufferExtension())
#endif
strategy = &strategyEXT;
else
strategy = &strategyNone;
}
loadVolatile();
}
Framebuffer::~Framebuffer()
{
// reset framebuffer if still using this one
if (current == this)
stopGrab();
unloadVolatile();
}
void Framebuffer::bindDefaultBuffer()
{
if (current != NULL)
current->stopGrab();
}
void Framebuffer::startGrab()
{
// already grabbing
if (current == this)
return;
// cleanup after previous fbo
if (current != NULL)
glPopAttrib();
// bind buffer and clear screen
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
strategy->bindFBO(fbo);
glClearColor(.0f, .0f, .0f, .0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
// indicate we are using this fbo
current = this;
}
void Framebuffer::stopGrab()
{
// i am not grabbing. leave me alone
if (current != this)
return;
// bind default
strategy->bindFBO( 0 );
glPopAttrib();
current = NULL;
}
void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
{
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy);
glPushMatrix();
glMultMatrixf((const GLfloat*)t.getElements());
glBindTexture(GL_TEXTURE_2D, img);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&vertices[0].s);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
}
love::image::ImageData * Framebuffer::getImageData(love::image::Image * image)
{
int row = 4 * width;
int size = row * height;
// see Graphics::newScreenshot. OpenGL reads from lower-left,
// but we need the pixels from upper-left.
GLubyte* pixels = new GLubyte[size];
GLubyte* screenshot = new GLubyte[size];
strategy->bindFBO( fbo );
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
if (current)
strategy->bindFBO( current->fbo );
else
strategy->bindFBO( 0 );
GLubyte* src = pixels - row; // second line of buffer
GLubyte* dst = screenshot + size; // end of buffer
for (int i = 0; i < height; ++i)
memcpy(dst -= row, src += row, row);
love::image::ImageData * img = image->newImageData(width, height, (void*)screenshot);
delete[] screenshot;
delete[] pixels;
return img;
}
bool Framebuffer::loadVolatile()
{
status = strategy->createFBO(fbo, depthbuffer, img, width, height);
return (status == GL_FRAMEBUFFER_COMPLETE);
}
void Framebuffer::unloadVolatile()
{
strategy->deleteFBO(fbo, depthbuffer, img);
}
} // opengl
} // graphics
} // love
+55
View File
@@ -0,0 +1,55 @@
#ifndef LOVE_GRAPHICS_FRAMEBUFFER_H
#define LOVE_GRAPHICS_FRAMEBUFFER_H
#include <graphics/Drawable.h>
#include <graphics/Volatile.h>
#include <image/Image.h>
#include <image/ImageData.h>
#include <common/math.h>
#include <map>
#include "GLee.h"
namespace love
{
namespace graphics
{
namespace opengl
{
class Framebuffer : public Drawable, public Volatile
{
public:
Framebuffer(int width, int height);
virtual ~Framebuffer();
unsigned int getStatus() const { return status; }
static Framebuffer* current;
static void bindDefaultBuffer();
void startGrab();
void stopGrab();
virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
love::image::ImageData * getImageData(love::image::Image * image);
bool loadVolatile();
void unloadVolatile();
private:
GLsizei width;
GLsizei height;
GLuint fbo;
GLuint depthbuffer;
GLuint img;
vertex vertices[4];
GLenum status;
};
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_FRAMEBUFFER_H
+5
View File
@@ -477,6 +477,11 @@ namespace opengl
return new ParticleSystem(image, size);
}
Framebuffer * Graphics::newFramebuffer(int width, int height)
{
return new Framebuffer(width, height);
}
void Graphics::setColor(Color c)
{
glColor4ubv(&c.r);
+28 -25
View File
@@ -1,14 +1,14 @@
/**
* Copyright (c) 2006-2010 LOVE Development Team
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
@@ -43,6 +43,7 @@
#include "Quad.h"
#include "SpriteBatch.h"
#include "ParticleSystem.h"
#include "Framebuffer.h"
namespace love
{
@@ -95,13 +96,13 @@ namespace opengl
// Default values.
DisplayState()
{
color.r = 255;
color.g = 255;
color.b = 255;
color.r = 255;
color.g = 255;
color.b = 255;
color.a = 255;
backgroundColor.r = 0;
backgroundColor.g = 0;
backgroundColor.b = 0;
backgroundColor.r = 0;
backgroundColor.g = 0;
backgroundColor.b = 0;
backgroundColor.a = 255;
blendMode = Graphics::BLEND_ALPHA;
colorMode = Graphics::COLOR_MODULATE;
@@ -126,7 +127,7 @@ namespace opengl
Graphics();
virtual ~Graphics();
// Implements Module.
const char * getName() const;
@@ -165,18 +166,18 @@ namespace opengl
* when the game reloads.
**/
void reset();
/**
* Clears the screen.
**/
void clear();
/**
* Flips buffers. (Rendered geometry is
* Flips buffers. (Rendered geometry is
* presented on screen).
**/
void present();
/**
* Sets the window's icon.
**/
@@ -207,13 +208,13 @@ namespace opengl
/**
* This native Lua function gets available modes
* from SDL and returns them as a table on the following format:
*
* {
* { width = 800, height = 600 },
*
* {
* { width = 800, height = 600 },
* { width = 1024, height = 768 },
* ...
* }
*
*
* Only fullscreen modes are returned here, as all
* window sizes are supported (normally).
**/
@@ -245,7 +246,7 @@ namespace opengl
**/
Image * newImage(love::filesystem::File * file);
Image * newImage(love::image::ImageData * data);
/**
* Creates a Frame
**/
@@ -255,11 +256,13 @@ namespace opengl
* Creates a Font object.
**/
Font * newFont(love::font::FontData * data);
SpriteBatch * newSpriteBatch(Image * image, int size, int usage);
ParticleSystem * newParticleSystem(Image * image, int size);
Framebuffer * newFramebuffer(int width, int height);
/**
* Sets the foreground color.
**/
@@ -271,7 +274,7 @@ namespace opengl
Color getColor();
/**
* Sets the background Color.
* Sets the background Color.
**/
void setBackgroundColor(Color c);
@@ -383,7 +386,7 @@ namespace opengl
PointStyle getPointStyle();
/**
* Gets the maximum point size supported.
* Gets the maximum point size supported.
* This may vary from computer to computer.
**/
int getMaxPointSize();
@@ -406,7 +409,7 @@ namespace opengl
void print(const char * str, float x, float y , float angle);
/**
* Draws text at the specified coordinates, with rotation and
* Draws text at the specified coordinates, with rotation and
* scaling.
* @param x The x-coordinate.
* @param y The y-coordinate.
@@ -416,7 +419,7 @@ namespace opengl
void print(const char * str, float x, float y , float angle, float s);
/**
* Draws text at the specified coordinates, with rotation and
* Draws text at the specified coordinates, with rotation and
* scaling along both axes.
* @param x The x-coordinate.
* @param y The y-coordinate.
@@ -452,7 +455,7 @@ namespace opengl
* @param y2 Second y-coordinate.
**/
void line(float x1, float y1, float x2, float y2);
/**
* Draws a series of lines connecting the given vertices.
* @param ... Vertex components (x1, y1, x2, y2, etc.)
@@ -0,0 +1,57 @@
#include "wrap_Framebuffer.h"
namespace love
{
namespace graphics
{
namespace opengl
{
Framebuffer * luax_checkfbo(lua_State * L, int idx)
{
return luax_checktype<Framebuffer>(L, idx, "Framebuffer", GRAPHICS_FRAMEBUFFER_T);
}
int w_Framebuffer_renderTo(lua_State * L)
{
// As startGrab() clears the framebuffer, better not allow
// grabbing inside another grabbing
if (Framebuffer::current != NULL) {
Framebuffer::bindDefaultBuffer();
return luaL_error(L, "Current render target not the default framebuffer!");
}
Framebuffer * fbo = luax_checkfbo(L, 1);
if (!lua_isfunction(L, 2))
return luaL_error(L, "Need a function to render to fbo");
fbo->startGrab();
lua_settop(L, 2); // make sure the function is on top of the stack
lua_call(L, 0, 0);
fbo->stopGrab();
return 0;
}
int w_Framebuffer_getImageData(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
love::image::Image * image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
love::image::ImageData * img = fbo->getImageData( image );
luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)img);
return 1;
}
static const luaL_Reg functions[] = {
{ "renderTo", w_Framebuffer_renderTo },
{ "getImageData", w_Framebuffer_getImageData },
{ 0, 0 }
};
int luaopen_framebuffer(lua_State * L)
{
return luax_register_type(L, "Framebuffer", functions);
}
} // opengl
} // graphics
} // love
@@ -0,0 +1,24 @@
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
#define LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
// LOVE
#include <common/runtime.h>
#include "Framebuffer.h"
namespace love
{
namespace graphics
{
namespace opengl
{
//see Framebuffer.h
Framebuffer * luax_checkfbo(lua_State * L, int idx);
int w_Framebuffer_renderTo(lua_State * L);
int w_Framebuffer_getImageData(lua_State * L);
int luaopen_framebuffer(lua_State * L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
+60 -2
View File
@@ -84,7 +84,7 @@ namespace opengl
instance->setIcon(image);
return 0;
}
int w_setCaption(lua_State * L)
{
const char * str = luaL_checkstring(L, 1);
@@ -292,6 +292,46 @@ namespace opengl
return 1;
}
int w_newFramebuffer(lua_State * L)
{
// check if width and height are given. else default to screen dimensions.
int width = luaL_optint(L, 1, instance->getWidth());
int height = luaL_optint(L, 2, instance->getHeight());
glGetError(); // clear opengl error flag
Framebuffer * framebuffer = instance->newFramebuffer(width, height);
//and there we go with the status... still disliked
if (framebuffer->getStatus() != GL_FRAMEBUFFER_COMPLETE) {
switch (framebuffer->getStatus()) {
case GL_FRAMEBUFFER_UNSUPPORTED:
return luaL_error(L, "Cannot create Framebuffer: "
"Not supported by your OpenGL implementation");
// remaining error codes are highly unlikely:
case GL_FRAMEBUFFER_UNDEFINED:
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
return luaL_error(L, "Cannot create Framebuffer: "
"Error in implementation (please inform the love devs)");
default:
// my intel hda card wrongly returns 0 to glCheckFramebufferStatus() but sets
// no error flag. I think it meant to return GL_FRAMEBUFFER_UNSUPPORTED, but who
// knows.
if (glGetError() == GL_NO_ERROR)
return luaL_error(L, "Cannot create Framebuffer: "
"May not be supported by your OpenGL implementation.");
// the remaining error is an indication of a serious fuckup since it should
// only be returned if glCheckFramebufferStatus() was called with the wrong
// arguments.
return luaL_error(L, "Cannot create Framebuffer: Aliens did it (OpenGL error code: %d)", glGetError());
}
}
luax_newtype(L, "Framebuffer", GRAPHICS_FRAMEBUFFER_T, (void*)framebuffer);
return 1;
}
int w_setColor(lua_State * L)
{
Color c;
@@ -567,6 +607,21 @@ namespace opengl
return 1;
}
int w_setRenderTarget(lua_State * L)
{
// called with nil or none -> reset to default buffer
if (lua_isnoneornil(L,1)) {
Framebuffer::bindDefaultBuffer();
return 0;
}
Framebuffer * fbo = luax_checkfbo(L, 1);
// this unbinds the previous fbo
fbo->startGrab();
return 0;
}
/**
* Draws an Image at the specified coordinates, with rotation and
* scaling along both axes.
@@ -829,6 +884,7 @@ namespace opengl
{ "newImageFont", w_newImageFont },
{ "newSpriteBatch", w_newSpriteBatch },
{ "newParticleSystem", w_newParticleSystem },
{ "newFramebuffer", w_newFramebuffer },
{ "setColor", w_setColor },
{ "getColor", w_getColor },
@@ -856,6 +912,7 @@ namespace opengl
{ "getPointStyle", w_getPointStyle },
{ "getMaxPointSize", w_getMaxPointSize },
{ "newScreenshot", w_newScreenshot },
{ "setRenderTarget", w_setRenderTarget },
{ "draw", w_draw },
{ "drawq", w_drawq },
@@ -866,7 +923,7 @@ namespace opengl
{ "setCaption", w_setCaption },
{ "getCaption", w_getCaption },
{ "setIcon", w_setIcon },
{ "getWidth", w_getWidth },
@@ -906,6 +963,7 @@ namespace opengl
luaopen_frame,
luaopen_spritebatch,
luaopen_particlesystem,
luaopen_framebuffer,
0
};
+6 -3
View File
@@ -1,14 +1,14 @@
/**
* Copyright (c) 2006-2010 LOVE Development Team
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
@@ -28,6 +28,7 @@
#include "wrap_Quad.h"
#include "wrap_SpriteBatch.h"
#include "wrap_ParticleSystem.h"
#include "wrap_Framebuffer.h"
#include "Graphics.h"
namespace love
@@ -58,6 +59,7 @@ namespace opengl
int w_newImageFont(lua_State * L);
int w_newSpriteBatch(lua_State * L);
int w_newParticleSystem(lua_State * L);
int w_newFramebuffer(lua_State * L); // commetns in function
int w_setColor(lua_State * L);
int w_getColor(lua_State * L);
int w_setBackgroundColor(lua_State * L);
@@ -82,6 +84,7 @@ namespace opengl
int w_getPointStyle(lua_State * L);
int w_getMaxPointSize(lua_State * L);
int w_newScreenshot(lua_State * L);
int w_setRenderTarget(lua_State * L);
int w_draw(lua_State * L);
int w_drawq(lua_State * L);
int w_drawTest(lua_State * L);
+2
View File
@@ -787,6 +787,8 @@ function love.errhand(msg)
return
end
love.graphics.setRenderTarget()
-- Load.
love.graphics.setScissor()
love.graphics.setBackgroundColor(89, 157, 220)
+91 -89
View File
@@ -1157,102 +1157,104 @@ const unsigned char boot_lua[] =
0x74,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
0x2E,0x69,0x73,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x28,0x29,0x20,0x74,0x68,
0x65,0x6E,0x0D,0x0A,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6E,0x0D,0x0A,0x09,
0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x09,0x2D,0x2D,0x20,0x4C,0x6F,0x61,0x64,
0x2E,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,
0x63,0x73,0x2E,0x73,0x65,0x74,0x53,0x63,0x69,0x73,0x73,0x6F,0x72,0x28,0x29,
0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,
0x73,0x2E,0x73,0x65,0x74,0x42,0x61,0x63,0x6B,0x67,0x72,0x6F,0x75,0x6E,0x64,
0x43,0x6F,0x6C,0x6F,0x72,0x28,0x38,0x39,0x2C,0x20,0x31,0x35,0x37,0x2C,0x20,
0x32,0x32,0x30,0x29,0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x66,0x6F,
0x6E,0x74,0x20,0x3D,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,
0x69,0x63,0x73,0x2E,0x6E,0x65,0x77,0x46,0x6F,0x6E,0x74,0x28,0x6C,0x6F,0x76,
0x65,0x2E,0x5F,0x76,0x65,0x72,0x61,0x5F,0x74,0x74,0x66,0x2C,0x20,0x31,0x34,
0x29,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,
0x63,0x73,0x2E,0x73,0x65,0x74,0x46,0x6F,0x6E,0x74,0x28,0x66,0x6F,0x6E,0x74,
0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,
0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x43,0x6F,0x6C,0x6F,0x72,0x28,0x32,
0x35,0x35,0x2C,0x20,0x32,0x35,0x35,0x2C,0x20,0x32,0x35,0x35,0x2C,0x20,0x32,
0x35,0x35,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x74,
0x72,0x61,0x63,0x65,0x20,0x3D,0x20,0x64,0x65,0x62,0x75,0x67,0x2E,0x74,0x72,
0x61,0x63,0x65,0x62,0x61,0x63,0x6B,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,
0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x63,0x6C,
0x65,0x61,0x72,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,
0x20,0x65,0x72,0x72,0x20,0x3D,0x20,0x7B,0x7D,0x0D,0x0A,0x0D,0x0A,0x09,0x74,
0x61,0x62,0x6C,0x65,0x2E,0x69,0x6E,0x73,0x65,0x72,0x74,0x28,0x65,0x72,0x72,
0x2C,0x20,0x22,0x45,0x72,0x72,0x6F,0x72,0x5C,0x6E,0x22,0x29,0x0D,0x0A,0x09,
0x74,0x61,0x62,0x6C,0x65,0x2E,0x69,0x6E,0x73,0x65,0x72,0x74,0x28,0x65,0x72,
0x72,0x2C,0x20,0x6D,0x73,0x67,0x2E,0x2E,0x22,0x5C,0x6E,0x5C,0x6E,0x22,0x29,
0x0D,0x0A,0x0D,0x0A,0x09,0x66,0x6F,0x72,0x20,0x6C,0x20,0x69,0x6E,0x20,0x73,
0x74,0x72,0x69,0x6E,0x67,0x2E,0x67,0x6D,0x61,0x74,0x63,0x68,0x28,0x74,0x72,
0x61,0x63,0x65,0x2C,0x20,0x22,0x28,0x2E,0x2D,0x29,0x5C,0x6E,0x22,0x29,0x20,
0x64,0x6F,0x0D,0x0A,0x09,0x09,0x69,0x66,0x20,0x6E,0x6F,0x74,0x20,0x73,0x74,
0x72,0x69,0x6E,0x67,0x2E,0x6D,0x61,0x74,0x63,0x68,0x28,0x6C,0x2C,0x20,0x22,
0x62,0x6F,0x6F,0x74,0x2E,0x6C,0x75,0x61,0x22,0x29,0x20,0x74,0x68,0x65,0x6E,
0x0D,0x0A,0x09,0x09,0x09,0x6C,0x20,0x3D,0x20,0x73,0x74,0x72,0x69,0x6E,0x67,
0x2E,0x67,0x73,0x75,0x62,0x28,0x6C,0x2C,0x20,0x22,0x73,0x74,0x61,0x63,0x6B,
0x20,0x74,0x72,0x61,0x63,0x65,0x62,0x61,0x63,0x6B,0x3A,0x22,0x2C,0x20,0x22,
0x54,0x72,0x61,0x63,0x65,0x62,0x61,0x63,0x6B,0x5C,0x6E,0x22,0x29,0x0D,0x0A,
0x09,0x09,0x09,0x74,0x61,0x62,0x6C,0x65,0x2E,0x69,0x6E,0x73,0x65,0x72,0x74,
0x28,0x65,0x72,0x72,0x2C,0x20,0x6C,0x29,0x0D,0x0A,0x09,0x09,0x65,0x6E,0x64,
0x0D,0x0A,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,
0x6C,0x20,0x70,0x20,0x3D,0x20,0x74,0x61,0x62,0x6C,0x65,0x2E,0x63,0x6F,0x6E,
0x63,0x61,0x74,0x28,0x65,0x72,0x72,0x2C,0x20,0x22,0x5C,0x6E,0x22,0x29,0x0D,
0x0A,0x0D,0x0A,0x09,0x70,0x20,0x3D,0x20,0x73,0x74,0x72,0x69,0x6E,0x67,0x2E,
0x67,0x73,0x75,0x62,0x28,0x70,0x2C,0x20,0x22,0x5C,0x74,0x22,0x2C,0x20,0x22,
0x22,0x29,0x0D,0x0A,0x09,0x70,0x20,0x3D,0x20,0x73,0x74,0x72,0x69,0x6E,0x67,
0x2E,0x67,0x73,0x75,0x62,0x28,0x70,0x2C,0x20,0x22,0x25,0x5B,0x73,0x74,0x72,
0x69,0x6E,0x67,0x20,0x5C,0x22,0x28,0x2E,0x2D,0x29,0x5C,0x22,0x25,0x5D,0x22,
0x2C,0x20,0x22,0x25,0x31,0x22,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x63,
0x61,0x6C,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,0x6F,0x6E,0x20,0x64,0x72,0x61,
0x77,0x28,0x29,0x0D,0x0A,0x09,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,
0x70,0x68,0x69,0x63,0x73,0x2E,0x63,0x6C,0x65,0x61,0x72,0x28,0x29,0x0D,0x0A,
0x09,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,
0x2E,0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x70,0x2C,0x20,0x37,0x30,0x2C,0x20,
0x37,0x30,0x2C,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,
0x63,0x73,0x2E,0x67,0x65,0x74,0x57,0x69,0x64,0x74,0x68,0x28,0x29,0x20,0x2D,
0x20,0x37,0x30,0x29,0x0D,0x0A,0x09,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,
0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x70,0x72,0x65,0x73,0x65,0x6E,0x74,0x28,
0x29,0x0D,0x0A,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x09,0x64,0x72,0x61,
0x77,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x65,
0x2C,0x20,0x61,0x2C,0x20,0x62,0x2C,0x20,0x63,0x0D,0x0A,0x09,0x77,0x68,0x69,
0x6C,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64,0x6F,0x0D,0x0A,0x09,0x09,0x65,
0x2C,0x20,0x61,0x2C,0x20,0x62,0x2C,0x20,0x63,0x20,0x3D,0x20,0x6C,0x6F,0x76,
0x65,0x2E,0x65,0x76,0x65,0x6E,0x74,0x2E,0x77,0x61,0x69,0x74,0x28,0x29,0x0D,
0x0A,0x0D,0x0A,0x09,0x09,0x69,0x66,0x20,0x65,0x20,0x3D,0x3D,0x20,0x22,0x71,
0x22,0x20,0x74,0x68,0x65,0x6E,0x0D,0x0A,0x09,0x09,0x09,0x72,0x65,0x74,0x75,
0x72,0x6E,0x0D,0x0A,0x09,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x09,0x09,0x69,0x66,
0x20,0x65,0x20,0x3D,0x3D,0x20,0x22,0x6B,0x70,0x22,0x20,0x61,0x6E,0x64,0x20,
0x61,0x20,0x3D,0x3D,0x20,0x22,0x65,0x73,0x63,0x61,0x70,0x65,0x22,0x20,0x74,
0x68,0x65,0x6E,0x0D,0x0A,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6E,0x0D,
0x0A,0x09,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x09,0x09,0x64,0x72,0x61,
0x77,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,
0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x0D,0x0A,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,
0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x52,0x65,0x6E,0x64,0x65,
0x72,0x54,0x61,0x72,0x67,0x65,0x74,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x2D,
0x2D,0x20,0x4C,0x6F,0x61,0x64,0x2E,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,
0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x53,0x63,0x69,
0x73,0x73,0x6F,0x72,0x28,0x29,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,
0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x42,0x61,0x63,0x6B,
0x67,0x72,0x6F,0x75,0x6E,0x64,0x43,0x6F,0x6C,0x6F,0x72,0x28,0x38,0x39,0x2C,
0x20,0x31,0x35,0x37,0x2C,0x20,0x32,0x32,0x30,0x29,0x0D,0x0A,0x09,0x6C,0x6F,
0x63,0x61,0x6C,0x20,0x66,0x6F,0x6E,0x74,0x20,0x3D,0x20,0x6C,0x6F,0x76,0x65,
0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x6E,0x65,0x77,0x46,0x6F,
0x6E,0x74,0x28,0x6C,0x6F,0x76,0x65,0x2E,0x5F,0x76,0x65,0x72,0x61,0x5F,0x74,
0x74,0x66,0x2C,0x20,0x31,0x34,0x29,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,
0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x46,0x6F,0x6E,
0x74,0x28,0x66,0x6F,0x6E,0x74,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x76,
0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x73,0x65,0x74,0x43,
0x6F,0x6C,0x6F,0x72,0x28,0x32,0x35,0x35,0x2C,0x20,0x32,0x35,0x35,0x2C,0x20,
0x32,0x35,0x35,0x2C,0x20,0x32,0x35,0x35,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,
0x6F,0x63,0x61,0x6C,0x20,0x74,0x72,0x61,0x63,0x65,0x20,0x3D,0x20,0x64,0x65,
0x62,0x75,0x67,0x2E,0x74,0x72,0x61,0x63,0x65,0x62,0x61,0x63,0x6B,0x28,0x29,
0x0D,0x0A,0x0D,0x0A,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,
0x69,0x63,0x73,0x2E,0x63,0x6C,0x65,0x61,0x72,0x28,0x29,0x0D,0x0A,0x0D,0x0A,
0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x65,0x72,0x72,0x20,0x3D,0x20,0x7B,0x7D,
0x0D,0x0A,0x0D,0x0A,0x09,0x74,0x61,0x62,0x6C,0x65,0x2E,0x69,0x6E,0x73,0x65,
0x72,0x74,0x28,0x65,0x72,0x72,0x2C,0x20,0x22,0x45,0x72,0x72,0x6F,0x72,0x5C,
0x6E,0x22,0x29,0x0D,0x0A,0x09,0x74,0x61,0x62,0x6C,0x65,0x2E,0x69,0x6E,0x73,
0x65,0x72,0x74,0x28,0x65,0x72,0x72,0x2C,0x20,0x6D,0x73,0x67,0x2E,0x2E,0x22,
0x5C,0x6E,0x5C,0x6E,0x22,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x66,0x6F,0x72,0x20,
0x6C,0x20,0x69,0x6E,0x20,0x73,0x74,0x72,0x69,0x6E,0x67,0x2E,0x67,0x6D,0x61,
0x74,0x63,0x68,0x28,0x74,0x72,0x61,0x63,0x65,0x2C,0x20,0x22,0x28,0x2E,0x2D,
0x29,0x5C,0x6E,0x22,0x29,0x20,0x64,0x6F,0x0D,0x0A,0x09,0x09,0x69,0x66,0x20,
0x6E,0x6F,0x74,0x20,0x73,0x74,0x72,0x69,0x6E,0x67,0x2E,0x6D,0x61,0x74,0x63,
0x68,0x28,0x6C,0x2C,0x20,0x22,0x62,0x6F,0x6F,0x74,0x2E,0x6C,0x75,0x61,0x22,
0x29,0x20,0x74,0x68,0x65,0x6E,0x0D,0x0A,0x09,0x09,0x09,0x6C,0x20,0x3D,0x20,
0x73,0x74,0x72,0x69,0x6E,0x67,0x2E,0x67,0x73,0x75,0x62,0x28,0x6C,0x2C,0x20,
0x22,0x73,0x74,0x61,0x63,0x6B,0x20,0x74,0x72,0x61,0x63,0x65,0x62,0x61,0x63,
0x6B,0x3A,0x22,0x2C,0x20,0x22,0x54,0x72,0x61,0x63,0x65,0x62,0x61,0x63,0x6B,
0x5C,0x6E,0x22,0x29,0x0D,0x0A,0x09,0x09,0x09,0x74,0x61,0x62,0x6C,0x65,0x2E,
0x69,0x6E,0x73,0x65,0x72,0x74,0x28,0x65,0x72,0x72,0x2C,0x20,0x6C,0x29,0x0D,
0x0A,0x09,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,
0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x70,0x20,0x3D,0x20,0x74,0x61,0x62,
0x6C,0x65,0x2E,0x63,0x6F,0x6E,0x63,0x61,0x74,0x28,0x65,0x72,0x72,0x2C,0x20,
0x22,0x5C,0x6E,0x22,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x70,0x20,0x3D,0x20,0x73,
0x74,0x72,0x69,0x6E,0x67,0x2E,0x67,0x73,0x75,0x62,0x28,0x70,0x2C,0x20,0x22,
0x5C,0x74,0x22,0x2C,0x20,0x22,0x22,0x29,0x0D,0x0A,0x09,0x70,0x20,0x3D,0x20,
0x73,0x74,0x72,0x69,0x6E,0x67,0x2E,0x67,0x73,0x75,0x62,0x28,0x70,0x2C,0x20,
0x22,0x25,0x5B,0x73,0x74,0x72,0x69,0x6E,0x67,0x20,0x5C,0x22,0x28,0x2E,0x2D,
0x29,0x5C,0x22,0x25,0x5D,0x22,0x2C,0x20,0x22,0x25,0x31,0x22,0x29,0x0D,0x0A,
0x0D,0x0A,0x09,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x66,0x75,0x6E,0x63,0x74,0x69,
0x6F,0x6E,0x20,0x64,0x72,0x61,0x77,0x28,0x29,0x0D,0x0A,0x09,0x09,0x6C,0x6F,
0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x63,0x6C,0x65,
0x61,0x72,0x28,0x29,0x0D,0x0A,0x09,0x09,0x6C,0x6F,0x76,0x65,0x2E,0x67,0x72,
0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x70,
0x2C,0x20,0x37,0x30,0x2C,0x20,0x37,0x30,0x2C,0x20,0x6C,0x6F,0x76,0x65,0x2E,
0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x67,0x65,0x74,0x57,0x69,0x64,
0x74,0x68,0x28,0x29,0x20,0x2D,0x20,0x37,0x30,0x29,0x0D,0x0A,0x09,0x09,0x6C,
0x6F,0x76,0x65,0x2E,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x2E,0x70,0x72,
0x65,0x73,0x65,0x6E,0x74,0x28,0x29,0x0D,0x0A,0x09,0x65,0x6E,0x64,0x0D,0x0A,
0x0D,0x0A,0x09,0x64,0x72,0x61,0x77,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x6C,
0x6F,0x63,0x61,0x6C,0x20,0x65,0x2C,0x20,0x61,0x2C,0x20,0x62,0x2C,0x20,0x63,
0x0D,0x0A,0x09,0x77,0x68,0x69,0x6C,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64,
0x6F,0x0D,0x0A,0x09,0x09,0x65,0x2C,0x20,0x61,0x2C,0x20,0x62,0x2C,0x20,0x63,
0x20,0x3D,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x65,0x76,0x65,0x6E,0x74,0x2E,0x77,
0x61,0x69,0x74,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x09,0x69,0x66,0x20,0x65,
0x20,0x3D,0x3D,0x20,0x22,0x71,0x22,0x20,0x74,0x68,0x65,0x6E,0x0D,0x0A,0x09,
0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6E,0x0D,0x0A,0x09,0x09,0x65,0x6E,0x64,
0x0D,0x0A,0x09,0x09,0x69,0x66,0x20,0x65,0x20,0x3D,0x3D,0x20,0x22,0x6B,0x70,
0x22,0x20,0x61,0x6E,0x64,0x20,0x61,0x20,0x3D,0x3D,0x20,0x22,0x65,0x73,0x63,
0x61,0x70,0x65,0x22,0x20,0x74,0x68,0x65,0x6E,0x0D,0x0A,0x09,0x09,0x09,0x72,
0x65,0x74,0x75,0x72,0x6E,0x0D,0x0A,0x09,0x09,0x65,0x6E,0x64,0x0D,0x0A,0x0D,
0x0A,0x09,0x09,0x64,0x72,0x61,0x77,0x28,0x29,0x0D,0x0A,0x0D,0x0A,0x09,0x65,
0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x65,0x6E,0x64,0x0D,0x0A,0x0D,0x0A,0x0D,0x0A,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x0D,0x0A,0x2D,0x2D,0x20,0x54,0x68,
0x65,0x20,0x72,0x6F,0x6F,0x74,0x20,0x6F,0x66,0x20,0x61,0x6C,0x6C,0x20,0x63,
0x61,0x6C,0x6C,0x73,0x2E,0x0D,0x0A,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x0D,
0x0A,0x2D,0x2D,0x20,0x54,0x68,0x65,0x20,0x72,0x6F,0x6F,0x74,0x20,0x6F,0x66,
0x20,0x61,0x6C,0x6C,0x20,0x63,0x61,0x6C,0x6C,0x73,0x2E,0x0D,0x0A,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x0D,0x0A,0x0D,0x0A,0x6C,0x6F,0x63,0x61,0x6C,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x0D,0x0A,0x0D,
0x0A,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x3D,
0x20,0x78,0x70,0x63,0x61,0x6C,0x6C,0x28,0x6C,0x6F,0x76,0x65,0x2E,0x62,0x6F,
0x6F,0x74,0x2C,0x20,0x65,0x72,0x72,0x6F,0x72,0x5F,0x70,0x72,0x69,0x6E,0x74,
0x65,0x72,0x29,0x0D,0x0A,0x69,0x66,0x20,0x6E,0x6F,0x74,0x20,0x72,0x65,0x73,
0x75,0x6C,0x74,0x20,0x74,0x68,0x65,0x6E,0x20,0x72,0x65,0x74,0x75,0x72,0x6E,
0x20,0x65,0x6E,0x64,0x0D,0x0A,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x72,0x65,0x73,
0x75,0x6C,0x74,0x20,0x3D,0x20,0x78,0x70,0x63,0x61,0x6C,0x6C,0x28,0x6C,0x6F,
0x76,0x65,0x2E,0x69,0x6E,0x69,0x74,0x2C,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x65,
0x72,0x72,0x68,0x61,0x6E,0x64,0x29,0x0D,0x0A,0x69,0x66,0x20,0x6E,0x6F,0x74,
0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x74,0x68,0x65,0x6E,0x20,0x72,0x65,
0x74,0x75,0x72,0x6E,0x20,0x65,0x6E,0x64,0x0D,0x0A,0x6C,0x6F,0x63,0x61,0x6C,
0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x3D,0x20,0x78,0x70,0x63,0x61,0x6C,
0x6C,0x28,0x6C,0x6F,0x76,0x65,0x2E,0x62,0x6F,0x6F,0x74,0x2C,0x20,0x65,0x72,
0x72,0x6F,0x72,0x5F,0x70,0x72,0x69,0x6E,0x74,0x65,0x72,0x29,0x0D,0x0A,0x69,
0x66,0x20,0x6E,0x6F,0x74,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x74,0x68,
0x65,0x6E,0x20,0x72,0x65,0x74,0x75,0x72,0x6E,0x20,0x65,0x6E,0x64,0x0D,0x0A,
0x6C,0x6F,0x63,0x61,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x3D,0x20,
0x78,0x70,0x63,0x61,0x6C,0x6C,0x28,0x6C,0x6F,0x76,0x65,0x2E,0x69,0x6E,0x69,
0x74,0x2C,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x65,0x72,0x72,0x68,0x61,0x6E,0x64,
0x29,0x0D,0x0A,0x69,0x66,0x20,0x6E,0x6F,0x74,0x20,0x72,0x65,0x73,0x75,0x6C,
0x74,0x20,0x74,0x68,0x65,0x6E,0x20,0x72,0x65,0x74,0x75,0x72,0x6E,0x20,0x65,
0x6E,0x64,0x0D,0x0A,0x6C,0x6F,0x63,0x61,0x6C,0x20,0x72,0x65,0x73,0x75,0x6C,
0x74,0x20,0x3D,0x20,0x78,0x70,0x63,0x61,0x6C,0x6C,0x28,0x6C,0x6F,0x76,0x65,
0x2E,0x72,0x75,0x6E,0x2C,0x20,0x6C,0x6F,0x76,0x65,0x2E,0x65,0x72,0x72,0x68,
0x61,0x6E,0x64,0x29,0x0D,0x0A,0x69,0x66,0x20,0x6E,0x6F,0x74,0x20,0x72,0x65,
0x73,0x75,0x6C,0x74,0x20,0x74,0x68,0x65,0x6E,0x20,0x72,0x65,0x74,0x75,0x72,
0x6E,0x20,0x65,0x6E,0x64,0x0D,0x0A,
0x6C,0x28,0x6C,0x6F,0x76,0x65,0x2E,0x72,0x75,0x6E,0x2C,0x20,0x6C,0x6F,0x76,
0x65,0x2E,0x65,0x72,0x72,0x68,0x61,0x6E,0x64,0x29,0x0D,0x0A,0x69,0x66,0x20,
0x6E,0x6F,0x74,0x20,0x72,0x65,0x73,0x75,0x6C,0x74,0x20,0x74,0x68,0x65,0x6E,
0x20,0x72,0x65,0x74,0x75,0x72,0x6E,0x20,0x65,0x6E,0x64,0x0D,0x0A,
};
// [/boot.lua]