b=524042, [webgl] texImage & texSubImage need to support flipY, r=vlad

This commit is contained in:
Mark Steele 2009-11-01 16:33:47 -08:00
Родитель 88afa1cc2e
Коммит 8b8423f08c
2 изменённых файлов: 187 добавлений и 181 удалений

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

@ -265,7 +265,8 @@ protected:
void MakeContextCurrent() { mGLPbuffer->MakeContextCurrent(); }
nsresult TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
gfxImageSurface **imageOut);
gfxImageSurface **imageOut,
bool flipY, bool premultiplyAlpha);
GLuint mActiveTexture;

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

@ -2334,7 +2334,8 @@ GL_SAME_METHOD_4(StencilOpSeparate, StencilOpSeparate, GLenum, GLenum, GLenum, G
nsresult
WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
gfxImageSurface **imageOut)
gfxImageSurface **imageOut,
bool flipY, bool premultiplyAlpha)
{
gfxImageSurface *surf = nsnull;
@ -2426,86 +2427,37 @@ WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
return NS_ERROR_FAILURE;
}
if (flipY) {
nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(res.mSize,
gfxASurface::ImageFormatARGB32);
if (!tmpsurf || tmpsurf->CairoStatus())
return NS_ERROR_FAILURE;
nsRefPtr<gfxContext> tmpctx = new gfxContext(tmpsurf);
if (!tmpctx || tmpctx->HasError())
return NS_ERROR_FAILURE;
tmpctx->Translate(gfxPoint(0, res.mSize.height));
tmpctx->Scale(1.0, -1.0);
tmpctx->NewPath();
tmpctx->Rectangle(gfxRect(0, 0, res.mSize.width, res.mSize.height));
tmpctx->SetSource(res.mSurface);
tmpctx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpctx->Fill();
NS_ADDREF(surf = tmpsurf);
tmpctx = nsnull;
}
res.mSurface.forget();
*imageOut = surf;
return NS_OK;
}
#if 0
NS_IMETHODIMP
WebGLContext::TexSubImage2DHTML(PRUint32 target, PRUint32 level, PRInt32 x, PRInt32 y, nsIDOMHTMLElement *imageOrCanvas)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
switch (target) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
default:
return ErrorMessage("texImage2DHTML: unsupported target");
}
nsRefPtr<gfxImageSurface> isurf;
nsresult rv;
rv = TexImageElementBase(imageOrCanvas,
getter_AddRefs(isurf));
if (NS_FAILED(rv))
return rv;
MakeContextCurrent();
gl->fTexSubImage2D(target, level, x, y, isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
return NS_OK;
}
NS_IMETHODIMP
WebGLContext::TexImage2DHTML(PRUint32 target, PRUint32 level, nsIDOMHTMLElement *imageOrCanvas)
{
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
switch (target) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
default:
return ErrorMessage("texImage2DHTML: unsupported target");
}
nsRefPtr<gfxImageSurface> isurf;
nsresult rv;
rv = TexImageElementBase(imageOrCanvas,
getter_AddRefs(isurf));
if (NS_FAILED(rv))
return rv;
MakeContextCurrent();
gl->fTexImage2D(target, level, LOCAL_GL_RGBA, isurf->Width(), isurf->Height(), 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
return NS_OK;
}
#endif /* XXX todo */
GL_SAME_METHOD_2(Uniform1i, Uniform1i, GLint, GLint)
GL_SAME_METHOD_3(Uniform2i, Uniform2i, GLint, GLint, GLint)
GL_SAME_METHOD_4(Uniform3i, Uniform3i, GLint, GLint, GLint, GLint)
@ -2946,142 +2898,196 @@ WebGLContext::ValidateGL()
NS_IMETHODIMP
WebGLContext::TexSubImage2D()
{
// XXX TODO
return NS_ERROR_FAILURE;
// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
// in GLsizei width, in GLsizei height,
// in GLenum format, in GLenum type, in CanvasArray pixels)
// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
// in ImageData pixels,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
// in HTMLImageElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
// in HTMLCanvasElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
// in HTMLVideoElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
#if 0
// XXX TODO
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
if (js.argc != 9) {
return ErrorMessage("texSubImage2D: expected 9 arguments");
if (js.argc < 5 || js.argc > 9) {
return ErrorMessage("texSubImage2D: expected 5 to 9 arguments");
return NS_ERROR_DOM_SYNTAX_ERR;
}
jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType;
JSObject *argPixelsObj;
jsuint argPixelsLen;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
&argTarget, &argLevel, &argX, &argY,
&argWidth, &argHeight, &argFormat, &argType,
&argPixelsObj) ||
!argPixelsObj ||
!::JS_IsArrayObject(js.ctx, argPixelsObj) ||
!::JS_GetArrayLength(js.ctx, argPixelsObj, &argPixelsLen))
{
return ErrorMessage("texSubImage2D: argument error");
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (js.argc < 8) {
jsuint argTarget, argLevel, argX, argY;
JSObject *argPixelsObj;
JSBool flipY = JS_FALSE;
JSBool premultiplyAlpha = JS_TRUE;
switch (argTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
default:
return ErrorMessage("texSubImage2D: unsupported target");
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuo/bb",
&argTarget, &argLevel, &argX, &argY,
&argPixelsObj, &flipY, &premultiplyAlpha) ||
!argPixelsObj)
{
return ErrorMessage("texSubImage2D: argument error");
return NS_ERROR_DOM_SYNTAX_ERR;
}
nsCOMPtr<nsIDOMHTMLElement> imgElt;
nsresult rv;
rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(imgElt));
nsRefPtr<gfxImageSurface> isurf;
rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha);
if (NS_FAILED(rv))
return ErrorMessage("texImage2D: failed to get image for element");
MakeContextCurrent();
gl->fTexSubImage2D (argTarget, argLevel, argX, argY, isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
} else {
jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType;
JSObject *argPixelsObj;
jsuint argPixelsLen;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
&argTarget, &argLevel, &argX, &argY,
&argWidth, &argHeight, &argFormat, &argType,
&argPixelsObj) ||
!argPixelsObj ||
!::JS_IsArrayObject(js.ctx, argPixelsObj) ||
!::JS_GetArrayLength(js.ctx, argPixelsObj, &argPixelsLen))
{
return ErrorMessage("texSubImage2D: argument error");
return NS_ERROR_DOM_SYNTAX_ERR;
}
switch (argTarget) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
break;
default:
return ErrorMessage("texSubImage2D: unsupported target");
return NS_ERROR_DOM_SYNTAX_ERR;
}
PRUint32 bufferType, bufferSize;
switch (argFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_GREEN:
case LOCAL_GL_BLUE:
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
bufferSize = 1;
break;
case LOCAL_GL_LUMINANCE_ALPHA:
bufferSize = 2;
break;
case LOCAL_GL_RGB:
bufferSize = 3;
break;
case LOCAL_GL_RGBA:
bufferSize = 4;
break;
default:
return ErrorMessage("texSubImage2D: pixel format not supported");
return NS_ERROR_DOM_SYNTAX_ERR;
}
switch (argType) {
case LOCAL_GL_SHORT:
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_BYTE:
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_INT:
case LOCAL_GL_UNSIGNED_INT:
case LOCAL_GL_FLOAT:
bufferType = argType;
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
bufferType = LOCAL_GL_UNSIGNED_SHORT;
break;
default:
return ErrorMessage("texSubImage2D: pixel packing not supported");
return NS_ERROR_DOM_SYNTAX_ERR;
}
// make sure the size is valid
PRInt32 tmp = argWidth * argHeight;
if (tmp && tmp / argHeight != argWidth) {
return ErrorMessage("texSubImage2D: too large width or height");
return NS_ERROR_DOM_SYNTAX_ERR;
}
}
PRUint32 bufferType, bufferSize;
switch (argFormat) {
case LOCAL_GL_RED:
case LOCAL_GL_GREEN:
case LOCAL_GL_BLUE:
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
bufferSize = 1;
break;
case LOCAL_GL_LUMINANCE_ALPHA:
bufferSize = 2;
break;
case LOCAL_GL_RGB:
bufferSize = 3;
break;
case LOCAL_GL_RGBA:
bufferSize = 4;
break;
default:
return ErrorMessage("texSubImage2D: pixel format not supported");
tmp = tmp * bufferSize;
if (tmp && tmp / bufferSize != (argWidth * argHeight)) {
return ErrorMessage("texSubImage2D: too large width or height (after multiplying with pixel size)");
return NS_ERROR_DOM_SYNTAX_ERR;
}
}
switch (argType) {
case LOCAL_GL_SHORT:
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_BYTE:
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_INT:
case LOCAL_GL_UNSIGNED_INT:
case LOCAL_GL_FLOAT:
bufferType = argType;
break;
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
bufferType = LOCAL_GL_UNSIGNED_SHORT;
break;
default:
return ErrorMessage("texSubImage2D: pixel packing not supported");
if ((PRUint32) tmp > argPixelsLen) {
return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
return NS_ERROR_DOM_SYNTAX_ERR;
}
SimpleBuffer sbuffer(bufferType, bufferSize, js.ctx, argPixelsObj, argPixelsLen);
if (!sbuffer.Valid())
return NS_ERROR_FAILURE;
MakeContextCurrent();
gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, (void *) sbuffer.data);
}
// make sure the size is valid
PRInt32 tmp = argWidth * argHeight;
if (tmp && tmp / argHeight != argWidth) {
return ErrorMessage("texSubImage2D: too large width or height");
return NS_ERROR_DOM_SYNTAX_ERR;
}
tmp = tmp * bufferSize;
if (tmp && tmp / bufferSize != (argWidth * argHeight)) {
return ErrorMessage("texSubImage2D: too large width or height (after multiplying with pixel size)");
return NS_ERROR_DOM_SYNTAX_ERR;
}
if ((PRUint32) tmp > argPixelsLen) {
return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
return NS_ERROR_DOM_SYNTAX_ERR;
}
SimpleBuffer sbuffer(bufferType, bufferSize, js.ctx, argPixelsObj, argPixelsLen);
if (!sbuffer.Valid())
return NS_ERROR_FAILURE;
MakeContextCurrent();
gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, (void *) sbuffer.data);
return NS_OK;
#endif
}
NS_IMETHODIMP
WebGLContext::TexImage2D()
{
//return NS_ERROR_FAILURE;
// void texImage2D(in GLenum target, in GLint level, in GLenum internalformat,
// in GLsizei width, in GLsizei height, in GLint border, in GLenum format,
// in GLenum type, in CanvasArray pixels)
// void texImage2D(in GLenum target, in GLint level, in ImageData pixels,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image,
// [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
// XXX TODO
//#if 0
NativeJSContext js;
if (NS_FAILED(js.error))
return js.error;
if (js.argc != 3 && js.argc != 9) {
return ErrorMessage("texImage2D: expected 3 or 9 arguments");
if (js.argc < 3 || js.argc > 9) {
return ErrorMessage("texImage2D: expected 3-5 or 9 arguments, got %d", js.argc);
return NS_ERROR_DOM_SYNTAX_ERR;
}
jsuint argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType;
if (js.argc == 3) {
if (js.argc > 2 && js.argc < 6) {
JSObject *argPixelsObj;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuo",
JSBool flipY = JS_FALSE;
JSBool premultiplyAlpha = JS_TRUE;
if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuo/bb",
&argTarget, &argLevel,
&argPixelsObj) ||
&argPixelsObj, &flipY, &premultiplyAlpha) ||
!argPixelsObj)
{
return ErrorMessage("texImage2D: argument error");
@ -3093,7 +3099,7 @@ WebGLContext::TexImage2D()
nsRefPtr<gfxImageSurface> isurf;
rv = TexImageElementBase(imgElt, getter_AddRefs(isurf));
rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha);
if (NS_FAILED(rv))
return ErrorMessage("texImage2D: failed to get image for element");
@ -3226,7 +3232,6 @@ WebGLContext::TexImage2D()
MakeContextCurrent();
gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, (void *) sbuffer.data);
}
//#endif
}
return NS_OK;
}