зеркало из https://github.com/mozilla/gecko-dev.git
b=566126; allow readpixels on arbitrary sized non-default framebuffer; r=vlad
This commit is contained in:
Родитель
ba7702e9b5
Коммит
ee8ba48977
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче