b=566126; allow readpixels on arbitrary sized non-default framebuffer; r=vlad

This commit is contained in:
Cedric Vivier 2010-05-15 20:07:30 +08:00
Родитель ba7702e9b5
Коммит ee8ba48977
2 изменённых файлов: 98 добавлений и 34 удалений

Просмотреть файл

@ -349,6 +349,39 @@ protected:
nsTArray<WebGLObjectBaseRefPtr *> mRefOwners;
};
class WebGLRectangleObject
{
protected:
WebGLRectangleObject()
: mWidth(0), mHeight(0) { }
public:
GLsizei width() { return mWidth; }
void width(GLsizei value) { mWidth = value; }
GLsizei height() { return mHeight; }
void height(GLsizei value) { mHeight = value; }
void setDimensions(GLsizei width, GLsizei height) {
mWidth = width;
mHeight = height;
}
void setDimensions(WebGLRectangleObject *rect) {
if (rect) {
mWidth = rect->width();
mHeight = rect->height();
} else {
mWidth = 0;
mHeight = 0;
}
}
protected:
GLsizei mWidth;
GLsizei mHeight;
};
#define WEBGLBUFFER_PRIVATE_IID \
{0xd69f22e9, 0x6f98, 0x48bd, {0xb6, 0x94, 0x34, 0x17, 0xed, 0x06, 0x11, 0xab}}
class WebGLBuffer :
@ -393,7 +426,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(WebGLBuffer, WEBGLBUFFER_PRIVATE_IID)
{0x4c19f189, 0x1f86, 0x4e61, {0x96, 0x21, 0x0a, 0x11, 0xda, 0x28, 0x10, 0xdd}}
class WebGLTexture :
public nsIWebGLTexture,
public WebGLZeroingObject
public WebGLZeroingObject,
public WebGLRectangleObject
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLTEXTURE_PRIVATE_IID)
@ -484,7 +518,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(WebGLShader, WEBGLSHADER_PRIVATE_IID)
{0x0052a16f, 0x4bc9, 0x4a55, {0x9d, 0xa3, 0x54, 0x95, 0xaa, 0x4e, 0x80, 0xb9}}
class WebGLFramebuffer :
public nsIWebGLFramebuffer,
public WebGLZeroingObject
public WebGLZeroingObject,
public WebGLRectangleObject
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLFRAMEBUFFER_PRIVATE_IID)
@ -514,7 +549,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(WebGLFramebuffer, WEBGLFRAMEBUFFER_PRIVATE_IID)
{0x3cbc2067, 0x5831, 0x4e3f, {0xac, 0x52, 0x7e, 0xf4, 0x5c, 0x04, 0xff, 0xae}}
class WebGLRenderbuffer :
public nsIWebGLRenderbuffer,
public WebGLZeroingObject
public WebGLZeroingObject,
public WebGLRectangleObject
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLRENDERBUFFER_PRIVATE_IID)

Просмотреть файл

@ -323,17 +323,20 @@ WebGLContext::BindFramebuffer(GLenum target, nsIWebGLFramebuffer *fbobj)
{
GLuint framebuffername;
PRBool isNull;
if (!GetGLName<WebGLFramebuffer>(fbobj, &framebuffername, &isNull))
return NS_ERROR_DOM_SYNTAX_ERR;
WebGLFramebuffer *wfb;
if (target != LOCAL_GL_FRAMEBUFFER) {
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorMessage("glBindFramebuffer: target must be GL_FRAMEBUFFER");
}
if (!GetConcreteObjectAndGLName(fbobj, &wfb, &framebuffername, &isNull))
return NS_ERROR_DOM_SYNTAX_ERR;
MakeContextCurrent();
gl->fBindFramebuffer(target, framebuffername);
mBoundFramebuffer = wfb;
return NS_OK;
}
@ -342,7 +345,9 @@ WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rbobj)
{
GLuint renderbuffername;
PRBool isNull;
if (!GetGLName<WebGLRenderbuffer>(rbobj, &renderbuffername, &isNull))
WebGLRenderbuffer *wrb;
if (!GetConcreteObjectAndGLName(rbobj, &wrb, &renderbuffername, &isNull))
return NS_ERROR_DOM_SYNTAX_ERR;
if (target != LOCAL_GL_RENDERBUFFER)
@ -352,6 +357,8 @@ WebGLContext::BindRenderbuffer(GLenum target, nsIWebGLRenderbuffer *rbobj)
gl->fBindRenderbuffer(target, renderbuffername);
mBoundRenderbuffer = wrb;
return NS_OK;
}
@ -1002,20 +1009,29 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum r
{
GLuint renderbuffername;
PRBool isNull;
if (!GetGLName<WebGLRenderbuffer>(rbobj, &renderbuffername, &isNull))
WebGLRenderbuffer *wrb;
if (!GetConcreteObjectAndGLName(rbobj, &wrb, &renderbuffername, &isNull))
return NS_ERROR_DOM_SYNTAX_ERR;
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorMessage("glFramebufferRenderbuffer: target must be GL_FRAMEBUFFER");
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
attachment != LOCAL_GL_STENCIL_ATTACHMENT)
{
return ErrorMessage("glFramebufferRenderbuffer: invalid attachment");
}
if (rbtarget != LOCAL_GL_RENDERBUFFER)
return ErrorMessage("glFramebufferRenderbuffer: rbtarget must be GL_RENDERBUFFER");
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
if (mBoundFramebuffer && attachment == LOCAL_GL_COLOR_ATTACHMENT0)
mBoundFramebuffer->setDimensions(wrb);
MakeContextCurrent();
gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
@ -1032,13 +1048,16 @@ WebGLContext::FramebufferTexture2D(GLenum target,
{
GLuint texturename;
PRBool isNull;
if (!GetGLName<WebGLTexture>(tobj, &texturename, &isNull))
WebGLTexture *wtex;
if (!GetConcreteObjectAndGLName(tobj, &wtex, &texturename, &isNull))
return NS_ERROR_DOM_SYNTAX_ERR;
if (target != LOCAL_GL_FRAMEBUFFER)
return ErrorMessage("glFramebufferTexture2D: target must be GL_FRAMEBUFFER");
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 || attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
attachment != LOCAL_GL_STENCIL_ATTACHMENT)
return ErrorMessage("glFramebufferTexture2D: invalid attachment");
@ -1051,6 +1070,10 @@ WebGLContext::FramebufferTexture2D(GLenum target,
if (level != 0)
return ErrorMessage("glFramebufferTexture2D: level must be 0");
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
if (mBoundFramebuffer && attachment == LOCAL_GL_COLOR_ATTACHMENT0)
mBoundFramebuffer->setDimensions(wtex);
// XXXXX we need to store/reference this attachment!
MakeContextCurrent();
@ -1966,10 +1989,10 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
return NS_ERROR_DOM_SECURITY_ERR;
}
MakeContextCurrent();
if (!CanvasUtils::CheckSaneSubrectSize(x,y,width,height, mWidth, mHeight))
return ErrorMessage("readPixels: rectangle outside canvas");
GLsizei boundWidth = mBoundFramebuffer ? mBoundFramebuffer->width() : mWidth;
GLsizei boundHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight;
if (!CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight))
return ErrorMessage("readPixels: rectangle outside framebuffer");
PRUint32 size = 0;
switch (format) {
@ -1995,30 +2018,32 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
return ErrorMessage("readPixels: unsupported pixel type");
}
PRUint32 len = width*height*size;
MakeContextCurrent();
nsAutoArrayPtr<PRUint8> data(new PRUint8[len]);
gl->fReadPixels((GLint)x, (GLint)y, width, height, format, type, (GLvoid *)data.get());
PRUint32 len = width * height * size;
JSObject *abufObject = js_CreateArrayBuffer(js.ctx, len);
if (!abufObject)
return NS_ERROR_FAILURE;
js::ArrayBuffer *abuf = js::ArrayBuffer::fromJSObject(abufObject);
nsAutoArrayPtr<jsval> jsvector(new jsval[len]);
for (PRUint32 i = 0; i < len; i++)
jsvector[i] = INT_TO_JSVAL(data[i]);
JSObject *dataArray = JS_NewArrayObject(js.ctx, len, jsvector);
if (!dataArray)
return NS_ERROR_OUT_OF_MEMORY;
JSObjectHelper retobj(&js);
retobj.DefineProperty("width", width);
retobj.DefineProperty("height", height);
retobj.DefineProperty("data", dataArray);
js.SetRetVal(retobj);
gl->fReadPixels((GLint) x, (GLint) y, width, height, format, type, (GLvoid *) abuf->data);
JSObject *retval = js_CreateTypedArrayWithBuffer(js.ctx, js::TypedArray::TYPE_UINT8, abufObject, 0, len);
js.SetRetVal(retval);
return NS_OK;
}
GL_SAME_METHOD_4(RenderbufferStorage, RenderbufferStorage, GLenum, GLenum, GLsizei, GLsizei)
NS_IMETHODIMP
WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
if (mBoundRenderbuffer)
mBoundRenderbuffer->setDimensions(width, height);
MakeContextCurrent();
gl->fRenderbufferStorage(target, internalformat, width, height);
return NS_OK;
}
GL_SAME_METHOD_2(SampleCoverage, SampleCoverage, float, GLboolean)
@ -2641,6 +2666,9 @@ WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, NULL);
}
if (mBound2DTextures[mActiveTexture])
mBound2DTextures[mActiveTexture]->setDimensions(width, height);
return NS_OK;
}