Bug 670573 - Add glTex(Sub)Image2D wrappers that correctly handle stride and alignment. r=derf

This commit is contained in:
Matt Woodrow 2011-07-25 19:32:56 +12:00
parent 3e07692ce3
commit ba6834dec3
3 changed files with 166 additions and 56 deletions

View File

@ -494,7 +494,6 @@ PlanarYCbCrImage::CopyData(Data& aDest, gfxIntSize& aDestSize,
{ {
aDest = aData; aDest = aData;
/* We always have a multiple of 16 width so we can force the stride */
aDest.mYStride = aDest.mYSize.width; aDest.mYStride = aDest.mYSize.width;
aDest.mCbCrStride = aDest.mCbCrSize.width; aDest.mCbCrStride = aDest.mCbCrSize.width;

View File

@ -1700,10 +1700,9 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
shader = ShaderProgramType(0); shader = ShaderProgramType(0);
} }
#ifndef USE_GLES2 PRInt32 stride = imageSurface->Stride();
fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH,
imageSurface->Stride() / pixelSize);
#ifndef USE_GLES2
internalformat = LOCAL_GL_RGBA; internalformat = LOCAL_GL_RGBA;
#else #else
internalformat = format; internalformat = format;
@ -1722,69 +1721,168 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
unsigned char *rectData = unsigned char *rectData =
data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft); data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft);
#ifdef USE_GLES2 NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
if (imageSurface->Stride() != iterRect->width * pixelSize) { "Must be uploading to the origin when we don't have an existing texture");
// Not using the whole row of texture data and GLES doesn't
// support GL_UNPACK_ROW_LENGTH. We need to upload each row
// separately.
if (!textureInited) {
fTexImage2D(LOCAL_GL_TEXTURE_2D,
0,
internalformat,
iterRect->width,
iterRect->height,
0,
format,
type,
NULL);
}
for (int h = 0; h < iterRect->height; h++) {
fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
0,
iterRect->x,
iterRect->y+h,
iterRect->width,
1,
format,
type,
rectData);
rectData += imageSurface->Stride();
}
continue;
}
#endif
if (textureInited) { if (textureInited) {
fTexSubImage2D(LOCAL_GL_TEXTURE_2D, TexSubImage2D(LOCAL_GL_TEXTURE_2D,
0, 0,
iterRect->x, iterRect->x,
iterRect->y, iterRect->y,
iterRect->width, iterRect->width,
iterRect->height, iterRect->height,
format, stride,
type, pixelSize,
rectData); format,
type,
rectData);
} else { } else {
fTexImage2D(LOCAL_GL_TEXTURE_2D, TexImage2D(LOCAL_GL_TEXTURE_2D,
0, 0,
internalformat, internalformat,
iterRect->width, iterRect->width,
iterRect->height, iterRect->height,
0, stride,
format, pixelSize,
type, 0,
rectData); format,
type,
rectData);
} }
} }
return shader;
}
static GLint GetAddressAlignment(ptrdiff_t aAddress)
{
if (!(aAddress & 0x7)) {
return 8;
} else if (!(aAddress & 0x3)) {
return 4;
} else if (!(aAddress & 0x1)) {
return 2;
} else {
return 1;
}
}
void
GLContext::TexImage2D(GLenum target, GLint level, GLint internalformat,
GLsizei width, GLsizei height, GLsizei stride,
GLint pixelsize, GLint border, GLenum format,
GLenum type, const GLvoid *pixels)
{
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
GetAddressAlignment((ptrdiff_t)stride)));
#ifndef USE_GLES2
fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, stride/pixelsize);
#else
if (stride != width * pixelsize) {
// Not using the whole row of texture data and GLES doesn't
// support GL_UNPACK_ROW_LENGTH. We need to upload each row
// separately.
fTexImage2D(target,
border,
internalformat,
width,
height,
border,
format,
type,
NULL);
const unsigned char *row = (const unsigned char *)pixels;
for (int h = 0; h < height; h++) {
fTexSubImage2D(target,
level,
0,
h,
width,
1,
format,
type,
row);
row += stride;
}
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
return;
}
#endif
fTexImage2D(target,
level,
internalformat,
width,
height,
border,
format,
type,
pixels);
#ifndef USE_GLES2 #ifndef USE_GLES2
fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0); fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
#endif #endif
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
}
return shader; void
GLContext::TexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei stride,
GLint pixelsize, GLenum format,
GLenum type, const GLvoid* pixels)
{
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
NS_MIN(GetAddressAlignment((ptrdiff_t)pixels),
GetAddressAlignment((ptrdiff_t)stride)));
#ifndef USE_GLES2
fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, stride/pixelsize);
#else
if (stride != width * pixelsize) {
// Not using the whole row of texture data and GLES doesn't
// support GL_UNPACK_ROW_LENGTH. We need to upload each row
// separately.
const unsigned char *row = (const unsigned char *)pixels;
for (int h = 0; h < height; h++) {
fTexSubImage2D(target,
level,
xoffset,
yoffset+h,
width,
1,
format,
type,
row);
row += stride;
}
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
return;
}
#endif
fTexSubImage2D(target,
level,
xoffset,
yoffset,
width,
height,
format,
type,
pixels);
#ifndef USE_GLES2
fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
#endif
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
} }
void void

View File

@ -862,6 +862,19 @@ public:
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0), const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
bool aPixelBuffer = PR_FALSE); bool aPixelBuffer = PR_FALSE);
void TexImage2D(GLenum target, GLint level, GLint internalformat,
GLsizei width, GLsizei height, GLsizei stride,
GLint pixelsize, GLint border, GLenum format,
GLenum type, const GLvoid *pixels);
void TexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei stride,
GLint pixelsize, GLenum format,
GLenum type, const GLvoid* pixels);
/** Helper for DecomposeIntoNoRepeatTriangles /** Helper for DecomposeIntoNoRepeatTriangles
*/ */
struct RectTriangles { struct RectTriangles {