Rename Framebuffer to Canvas (issue #263). Move error reporting code.

Error reporting now resides in Graphics::newCanvas() instead of the
previous location wrap_newFramebuffer(). Changed error text for
"Error in implementation" to point to a possible fix.
This commit is contained in:
vrld
2011-08-12 14:41:18 +02:00
parent 59a407bc6d
commit 28b4008797
16 changed files with 187 additions and 166 deletions
@@ -1,4 +1,4 @@
#include "Framebuffer.h"
#include "Canvas.h"
#include "Graphics.h"
#include <common/Matrix.h>
@@ -140,9 +140,9 @@ namespace opengl
FramebufferStrategyEXT strategyEXT;
Framebuffer* Framebuffer::current = NULL;
Canvas* Canvas::current = NULL;
Framebuffer::Framebuffer(int width, int height) :
Canvas::Canvas(int width, int height) :
width(width), height(height)
{
strategy = NULL;
@@ -174,7 +174,7 @@ namespace opengl
loadVolatile();
}
Framebuffer::~Framebuffer()
Canvas::~Canvas()
{
// reset framebuffer if still using this one
if (current == this)
@@ -183,7 +183,7 @@ namespace opengl
unloadVolatile();
}
bool Framebuffer::isSupported()
bool Canvas::isSupported()
{
if (!strategy) {
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
@@ -196,13 +196,13 @@ namespace opengl
return (strategy != &strategyNone);
}
void Framebuffer::bindDefaultBuffer()
void Canvas::bindDefaultCanvas()
{
if (current != NULL)
current->stopGrab();
}
void Framebuffer::startGrab()
void Canvas::startGrab()
{
// already grabbing
if (current == this)
@@ -233,7 +233,7 @@ namespace opengl
current = this;
}
void Framebuffer::stopGrab()
void Canvas::stopGrab()
{
// i am not grabbing. leave me alone
if (current != this)
@@ -248,7 +248,7 @@ namespace opengl
}
void Framebuffer::clear(const Color& c)
void Canvas::clear(const Color& c)
{
GLuint previous = 0;
if (current != NULL)
@@ -263,7 +263,7 @@ namespace opengl
strategy->bindFBO(previous);
}
void Framebuffer::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky) const
{
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
@@ -284,7 +284,7 @@ namespace opengl
glPopMatrix();
}
love::image::ImageData * Framebuffer::getImageData(love::image::Image * image)
love::image::ImageData * Canvas::getImageData(love::image::Image * image)
{
int row = 4 * width;
int size = row * height;
@@ -315,7 +315,7 @@ namespace opengl
return img;
}
void Framebuffer::setFilter(const Image::Filter &f)
void Canvas::setFilter(const Image::Filter &f)
{
GLint gmin = (f.min == Image::FILTER_NEAREST) ? GL_NEAREST : GL_LINEAR;
GLint gmag = (f.mag == Image::FILTER_NEAREST) ? GL_NEAREST : GL_LINEAR;
@@ -326,7 +326,7 @@ namespace opengl
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag);
}
Image::Filter Framebuffer::getFilter() const
Image::Filter Canvas::getFilter() const
{
GLint gmin, gmag;
@@ -340,7 +340,7 @@ namespace opengl
return f;
}
void Framebuffer::setWrap(const Image::Wrap &w)
void Canvas::setWrap(const Image::Wrap &w)
{
GLint wrap_s = (w.s == Image::WRAP_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
GLint wrap_t = (w.t == Image::WRAP_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
@@ -350,7 +350,7 @@ namespace opengl
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t);
}
Image::Wrap Framebuffer::getWrap() const
Image::Wrap Canvas::getWrap() const
{
GLint wrap_s, wrap_t;
glBindTexture(GL_TEXTURE_2D, img);
@@ -364,7 +364,7 @@ namespace opengl
return w;
}
bool Framebuffer::loadVolatile()
bool Canvas::loadVolatile()
{
status = strategy->createFBO(fbo, depthbuffer, img, width, height);
if (status != GL_FRAMEBUFFER_COMPLETE)
@@ -378,19 +378,19 @@ namespace opengl
return true;
}
void Framebuffer::unloadVolatile()
void Canvas::unloadVolatile()
{
settings.filter = getFilter();
settings.wrap = getWrap();
strategy->deleteFBO(fbo, depthbuffer, img);
}
int Framebuffer::getWidth()
int Canvas::getWidth()
{
return width;
}
int Framebuffer::getHeight()
int Canvas::getHeight()
{
return height;
}
@@ -1,5 +1,5 @@
#ifndef LOVE_GRAPHICS_FRAMEBUFFER_H
#define LOVE_GRAPHICS_FRAMEBUFFER_H
#ifndef LOVE_GRAPHICS_CANVAS_H
#define LOVE_GRAPHICS_CANVAS_H
#include <graphics/Drawable.h>
#include <graphics/Volatile.h>
@@ -16,18 +16,18 @@ namespace graphics
{
namespace opengl
{
class Framebuffer : public Drawable, public Volatile
class Canvas : public Drawable, public Volatile
{
public:
Framebuffer(int width, int height);
virtual ~Framebuffer();
Canvas(int width, int height);
virtual ~Canvas();
static bool isSupported();
unsigned int getStatus() const { return status; }
static Framebuffer* current;
static void bindDefaultBuffer();
static Canvas* current;
static void bindDefaultCanvas();
void startGrab();
void stopGrab();
@@ -73,4 +73,4 @@ namespace opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_FRAMEBUFFER_H
#endif // LOVE_GRAPHICS_CANVAS_H
+46 -5
View File
@@ -313,7 +313,7 @@ namespace opengl
{
DisplayState s;
discardMask();
Framebuffer::bindDefaultBuffer();
Canvas::bindDefaultCanvas();
restoreState(s);
}
@@ -378,8 +378,8 @@ namespace opengl
int Graphics::getRenderHeight()
{
if (Framebuffer::current)
return Framebuffer::current->getHeight();
if (Canvas::current)
return Canvas::current->getHeight();
return currentMode.height;
}
@@ -533,9 +533,50 @@ namespace opengl
return new ParticleSystem(image, size);
}
Framebuffer * Graphics::newFramebuffer(int width, int height)
Canvas * Graphics::newCanvas(int width, int height)
{
return new Framebuffer(width, height);
Canvas * canvas = new Canvas(width, height);
GLenum err = canvas->getStatus();
// everything ok, reaturn canvas (early out)
if (err == GL_FRAMEBUFFER_COMPLETE)
return canvas;
// create error message
std::stringstream error_string;
error_string << "Cannot create canvas: ";
switch (err) {
case GL_FRAMEBUFFER_UNSUPPORTED:
error_string << "Not supported by your OpenGL implementation.";
break;
// 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:
error_string << "Error in implementation. Possible fix: Make canvas width and height powers of two.";
break;
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)
error_string << "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.
else
error_string << "Cannot create canvas: Aliens did it (OpenGL error code: " << glGetError() << ")";
}
canvas->release();
throw Exception(error_string.str().c_str());
return NULL; // never reached
}
PixelEffect * Graphics::newPixelEffect(const std::string& code)
+2 -2
View File
@@ -41,7 +41,7 @@
#include "Quad.h"
#include "SpriteBatch.h"
#include "ParticleSystem.h"
#include "Framebuffer.h"
#include "Canvas.h"
#include "PixelEffect.h"
namespace love
@@ -287,7 +287,7 @@ namespace opengl
ParticleSystem * newParticleSystem(Image * image, int size);
Framebuffer * newFramebuffer(int width, int height);
Canvas * newCanvas(int width, int height);
PixelEffect * newPixelEffect(const std::string& code);
+2 -2
View File
@@ -223,7 +223,7 @@ namespace opengl
checkSetUniformError();
}
void PixelEffect::sendFramebuffer(const std::string& name, const Framebuffer& fb)
void PixelEffect::sendCanvas(const std::string& name, const Canvas& canvas)
{
GLint texture_unit = getTextureUnit(name);
@@ -231,7 +231,7 @@ namespace opengl
GLint location = getUniformLocation(name);
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, fb.getTextureName());
glBindTexture(GL_TEXTURE_2D, canvas.getTextureName());
glUniform1i(location, texture_unit);
// reset texture unit
+2 -2
View File
@@ -5,7 +5,7 @@
#include <string>
#include <map>
#include "Image.h"
#include "Framebuffer.h"
#include "Canvas.h"
namespace love
{
@@ -31,7 +31,7 @@ namespace opengl
void sendFloat(const std::string& name, int count, const GLfloat* vec);
void sendMatrix(const std::string& name, int size, const GLfloat* m);
void sendImage(const std::string& name, const Image& image);
void sendFramebuffer(const std::string& name, const Framebuffer& fb);
void sendCanvas(const std::string& name, const Canvas& canvas);
private:
GLint getUniformLocation(const std::string& name);
@@ -1,5 +1,5 @@
#include "Graphics.h"
#include "wrap_Framebuffer.h"
#include "wrap_Canvas.h"
namespace love
{
@@ -7,44 +7,44 @@ namespace graphics
{
namespace opengl
{
Framebuffer * luax_checkfbo(lua_State * L, int idx)
Canvas * luax_checkcanvas(lua_State * L, int idx)
{
return luax_checktype<Framebuffer>(L, idx, "Framebuffer", GRAPHICS_FRAMEBUFFER_T);
return luax_checktype<Canvas>(L, idx, "Canvas", GRAPHICS_CANVAS_T);
}
int w_Framebuffer_renderTo(lua_State * L)
int w_Canvas_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!");
if (Canvas::current != NULL) {
Canvas::bindDefaultCanvas();
return luaL_error(L, "Current render target not the default canvas!");
}
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
if (!lua_isfunction(L, 2))
return luaL_error(L, "Need a function to render to fbo");
return luaL_error(L, "Need a function to render to canvas.");
fbo->startGrab();
canvas->startGrab();
lua_settop(L, 2); // make sure the function is on top of the stack
lua_call(L, 0, 0);
fbo->stopGrab();
canvas->stopGrab();
return 0;
}
int w_Framebuffer_getImageData(lua_State * L)
int w_Canvas_getImageData(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
love::image::Image * image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
love::image::ImageData * img = fbo->getImageData( image );
love::image::ImageData * img = canvas->getImageData( image );
luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)img);
return 1;
}
int w_Framebuffer_setFilter(lua_State * L)
int w_Canvas_setFilter(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
const char * minstr = luaL_checkstring(L, 2);
const char * magstr = luaL_checkstring(L, 3);
@@ -54,14 +54,14 @@ namespace opengl
if (!Image::getConstant(magstr, f.mag))
return luaL_error(L, "Invalid max filter mode: %s", magstr);
fbo->setFilter(f);
canvas->setFilter(f);
return 0;
}
int w_Framebuffer_getFilter(lua_State * L)
int w_Canvas_getFilter(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Image::Filter f = fbo->getFilter();
Canvas * canvas = luax_checkcanvas(L, 1);
Image::Filter f = canvas->getFilter();
const char * minstr;
const char * magstr;
@@ -74,9 +74,9 @@ namespace opengl
return 2;
}
int w_Framebuffer_setWrap(lua_State * L)
int w_Canvas_setWrap(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
const char * wrap_s = luaL_checkstring(L, 2);
const char * wrap_t = luaL_checkstring(L, 3);
@@ -86,14 +86,14 @@ namespace opengl
if (!Image::getConstant(wrap_t, w.t))
return luaL_error(L, "Invalid wrap mode: %s", wrap_t);
fbo->setWrap(w);
canvas->setWrap(w);
return 0;
}
int w_Framebuffer_getWrap(lua_State * L)
int w_Canvas_getWrap(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Image::Wrap w = fbo->getWrap();
Canvas * canvas = luax_checkcanvas(L, 1);
Image::Wrap w = canvas->getWrap();
const char * wrap_s;
const char * wrap_t;
@@ -106,9 +106,9 @@ namespace opengl
return 2;
}
int w_Framebuffer_clear(lua_State * L)
int w_Canvas_clear(lua_State * L)
{
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
Color c;
if (lua_isnoneornil(L, 2)) {
c.r = 0;
@@ -135,25 +135,25 @@ namespace opengl
c.b = (unsigned char)luaL_checkint(L, 4);
c.a = (unsigned char)luaL_optint(L, 5, 255);
}
fbo->clear(c);
canvas->clear(c);
return 0;
}
static const luaL_Reg functions[] = {
{ "renderTo", w_Framebuffer_renderTo },
{ "getImageData", w_Framebuffer_getImageData },
{ "setFilter", w_Framebuffer_setFilter },
{ "getFilter", w_Framebuffer_getFilter },
{ "setWrap", w_Framebuffer_setWrap },
{ "getWrap", w_Framebuffer_getWrap },
{ "clear", w_Framebuffer_clear },
{ "renderTo", w_Canvas_renderTo },
{ "getImageData", w_Canvas_getImageData },
{ "setFilter", w_Canvas_setFilter },
{ "getFilter", w_Canvas_getFilter },
{ "setWrap", w_Canvas_setWrap },
{ "getWrap", w_Canvas_getWrap },
{ "clear", w_Canvas_clear },
{ 0, 0 }
};
int luaopen_framebuffer(lua_State * L)
int luaopen_canvas(lua_State * L)
{
return luax_register_type(L, "Framebuffer", functions);
return luax_register_type(L, "Canvas", functions);
}
} // opengl
+29
View File
@@ -0,0 +1,29 @@
#ifndef LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H
#define LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H
// LOVE
#include <common/runtime.h>
#include "Canvas.h"
namespace love
{
namespace graphics
{
namespace opengl
{
//see Canvas.h
Canvas * luax_checkcanvas(lua_State * L, int idx);
int w_Canvas_renderTo(lua_State * L);
int w_Canvas_getImageData(lua_State * L);
int w_Canvas_setFilter(lua_State * L);
int w_Canvas_getFilter(lua_State * L);
int w_Canvas_setWrap(lua_State * L);
int w_Canvas_getWrap(lua_State * L);
int w_Canvas_clear(lua_State * L);
int luaopen_canvas(lua_State * L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_CANVAS_H
@@ -1,29 +0,0 @@
#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 w_Framebuffer_setFilter(lua_State * L);
int w_Framebuffer_getFilter(lua_State * L);
int w_Framebuffer_setWrap(lua_State * L);
int w_Framebuffer_getWrap(lua_State * L);
int w_Framebuffer_clear(lua_State * L);
int luaopen_framebuffer(lua_State * L);
} // opengl
} // graphics
} // love
#endif // LOVE_GRAPHICS_OPENGL_WRAP_FBO_H
+21 -41
View File
@@ -343,43 +343,24 @@ namespace opengl
return 1;
}
int w_newFramebuffer(lua_State * L)
int w_newCanvas(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());
}
Canvas * canvas = NULL;
try {
canvas = instance->newCanvas(width, height);
} catch (Exception& e) {
return luaL_error(L, e.what());
}
luax_newtype(L, "Framebuffer", GRAPHICS_FRAMEBUFFER_T, (void*)framebuffer);
if (NULL == canvas)
return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void*)canvas);
return 1;
}
@@ -718,24 +699,23 @@ namespace opengl
{
// called with nil or none -> reset to default buffer
if (lua_isnoneornil(L,1)) {
Framebuffer::bindDefaultBuffer();
Canvas::bindDefaultCanvas();
return 0;
}
Framebuffer * fbo = luax_checkfbo(L, 1);
Canvas * canvas = luax_checkcanvas(L, 1);
// this unbinds the previous fbo
fbo->startGrab();
canvas->startGrab();
return 0;
}
int w_getRenderTarget(lua_State * L)
{
Framebuffer *fbo = Framebuffer::current;
if (fbo)
{
fbo->retain();
luax_newtype(L, "Framebuffer", GRAPHICS_FRAMEBUFFER_T, (void*) fbo);
Canvas *canvas = Canvas::current;
if (canvas) {
canvas->retain();
luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void*) canvas);
}
else
lua_pushnil(L);
@@ -767,7 +747,7 @@ namespace opengl
switch(support)
{
case Graphics::SUPPORT_FRAMEBUFFERS:
if (!Framebuffer::isSupported())
if (!Canvas::isSupported())
supported = false;
break;
case Graphics::SUPPORT_PIXELEFFECTS:
@@ -1156,7 +1136,7 @@ namespace opengl
{ "newImageFont", w_newImageFont },
{ "newSpriteBatch", w_newSpriteBatch },
{ "newParticleSystem", w_newParticleSystem },
{ "newFramebuffer", w_newFramebuffer },
{ "newCanvas", w_newCanvas },
{ "newPixelEffect", w_newPixelEffect },
{ "setColor", w_setColor },
@@ -1245,7 +1225,7 @@ namespace opengl
luaopen_frame,
luaopen_spritebatch,
luaopen_particlesystem,
luaopen_framebuffer,
luaopen_canvas,
luaopen_pixeleffect,
0
};
+2 -2
View File
@@ -27,7 +27,7 @@
#include "wrap_Quad.h"
#include "wrap_SpriteBatch.h"
#include "wrap_ParticleSystem.h"
#include "wrap_Framebuffer.h"
#include "wrap_Canvas.h"
#include "wrap_PixelEffect.h"
#include "Graphics.h"
@@ -61,7 +61,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); // comments in function
int w_newCanvas(lua_State * L); // comments in function
int w_newPixelEffect(lua_State * L);
int w_setColor(lua_State * L);
int w_getColor(lua_State * L);
@@ -1,6 +1,6 @@
#include "wrap_PixelEffect.h"
#include "wrap_Image.h"
#include "wrap_Framebuffer.h"
#include "wrap_Canvas.h"
#include <string>
namespace love
@@ -81,14 +81,14 @@ namespace opengl
return 0;
}
int w_PixelEffect_sendFramebuffer(lua_State * L)
int w_PixelEffect_sendCanvas(lua_State * L)
{
PixelEffect * effect = luax_checkpixeleffect(L, 1);
const char* name = luaL_checkstring(L, 2);
Framebuffer* fb = luax_checkfbo(L, 3);
Canvas* canvas = luax_checkcanvas(L, 3);
try {
effect->sendFramebuffer(name, *fb);
effect->sendCanvas(name, *canvas);
} catch(love::Exception& e) {
luaL_error(L, e.what());
}
@@ -98,11 +98,11 @@ namespace opengl
static const luaL_Reg functions[] = {
{ "getWarnings", w_PixelEffect_getWarnings },
{ "sendFloat", w_PixelEffect_sendFloat },
{ "sendMatrix", w_PixelEffect_sendMatrix },
{ "sendImage", w_PixelEffect_sendImage },
{ "sendFramebuffer", w_PixelEffect_sendFramebuffer },
{ "getWarnings", w_PixelEffect_getWarnings },
{ "sendFloat", w_PixelEffect_sendFloat },
{ "sendMatrix", w_PixelEffect_sendMatrix },
{ "sendImage", w_PixelEffect_sendImage },
{ "sendCanvas", w_PixelEffect_sendCanvas },
{ 0, 0 }
};