diff --git a/gfx/gl/GLReadTexImageHelper.cpp b/gfx/gl/GLReadTexImageHelper.cpp index bb4e3100df2..17ac558e6b2 100644 --- a/gfx/gl/GLReadTexImageHelper.cpp +++ b/gfx/gl/GLReadTexImageHelper.cpp @@ -156,7 +156,8 @@ GLReadTexImageHelper::DidGLErrorOccur(const char* str) } static bool -GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType, +GetActualReadFormats(GLContext* gl, + GLenum destFormat, GLenum destType, GLenum& readFormat, GLenum& readType) { if (destFormat == LOCAL_GL_RGBA && @@ -231,16 +232,43 @@ static void SwapRAndBComponents(DataSourceSurface* surf) } } +static int +CalcStride(int width, int pixelSize, int alignment) +{ + MOZ_ASSERT(alignment); + + int stride = width * pixelSize; + if (stride % alignment) { // Extra at the end of the line? + int alignmentCount = stride / alignment; + stride = (alignmentCount+1) * alignment; + } + return stride; +} + +static int +GuessAlignment(int width, int pixelSize, int stride) +{ + int alignment = 8; // Max GLES allows. + while (CalcStride(width, pixelSize, alignment) != stride) { + alignment /= 2; + if (!alignment) { + MOZ_ASSERT(alignment); + return 1; + } + } + return alignment; +} + void ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { gl->MakeCurrent(); MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0)); /* gfxImageFormat::ARGB32: - * RGBA+UByte: be[RGBA], le[ABGR] - * RGBA+UInt: le[RGBA] - * BGRA+UInt: le[BGRA] - * BGRA+UIntRev: le[ARGB] + * RGBA+UByte: be[RGBA], le[ABGR] + * RGBA+UInt: be[ABGR], le[RGBA] + * BGRA+UInt: be[ARGB], le[BGRA] + * BGRA+UIntRev: be[BGRA], le[ARGB] * * gfxImageFormat::RGB16_565: * RGB+UShort: le[rrrrrggg,gggbbbbb] @@ -269,7 +297,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { default: MOZ_CRASH("Bad format."); } - MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize); + MOZ_ASSERT(dest->Width() * destPixelSize <= dest->Stride()); GLenum readFormat = destFormat; GLenum readType = destType; @@ -279,7 +307,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { nsAutoPtr tempSurf; gfxImageSurface* readSurf = nullptr; - int readPixelSize = 0; + int readAlignment = 0; if (needsTempSurf) { if (gl->DebugMode()) { NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!"); @@ -294,7 +322,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { break; } case LOCAL_GL_RGB: { - MOZ_ASSERT(readPixelSize == 2); + MOZ_ASSERT(destPixelSize == 2); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV); readFormatGFX = SurfaceFormat::R5G6B5; break; @@ -307,17 +335,17 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { switch (readType) { case LOCAL_GL_UNSIGNED_BYTE: { MOZ_ASSERT(readFormat == LOCAL_GL_RGBA); - readPixelSize = 4; + readAlignment = 1; break; } case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: { MOZ_ASSERT(readFormat == LOCAL_GL_BGRA); - readPixelSize = 4; + readAlignment = 4; break; } case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: { MOZ_ASSERT(readFormat == LOCAL_GL_RGB); - readPixelSize = 2; + readAlignment = 2; break; } default: { @@ -330,16 +358,20 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { false); readSurf = tempSurf; } else { - readPixelSize = destPixelSize; + // Figure out alignment. We don't need to know why, we just need it + // to be valid. + readAlignment = GuessAlignment(dest->Width(), + destPixelSize, + dest->Stride()); readSurf = dest; } - MOZ_ASSERT(readPixelSize); + MOZ_ASSERT(readAlignment); GLint currentPackAlignment = 0; gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment); - if (currentPackAlignment != readPixelSize) - gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize); + if (currentPackAlignment != readAlignment) + gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment); GLsizei width = dest->Width(); GLsizei height = dest->Height(); @@ -351,7 +383,7 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { readSurf->Data()); readSurf->MarkDirty(); - if (currentPackAlignment != readPixelSize) + if (currentPackAlignment != readAlignment) gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment); if (readSurf != dest) { @@ -387,6 +419,8 @@ ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { if (!alphaBits) { const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0); + MOZ_ASSERT(dest->Width() * destPixelSize == dest->Stride()); + dest->Flush(); uint32_t* itr = (uint32_t*)dest->Data(); uint32_t testPixel = *itr;