Bug 686742 - Move YUV conversion code into gfxUtil functions. r=derf

This commit is contained in:
Oleg Romashin
2011-09-27 15:19:24 -07:00
parent 8e28c97f8a
commit 23edca1891
4 changed files with 171 additions and 114 deletions

View File

@@ -42,11 +42,12 @@
#include "gfxPattern.h"
#include "nsThreadUtils.h"
#include "nsCoreAnimationSupport.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/mozalloc.h"
class nsIOSurface;
namespace mozilla {
namespace layers {

View File

@@ -47,8 +47,7 @@
#include "cairo.h"
#include "yuv_convert.h"
#include "ycbcr_to_rgb565.h"
#include "gfxUtils.h"
#include "gfxPlatform.h"
@@ -156,54 +155,10 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
return;
}
gfx::YUVType type =
gfx::TypeFromSize(aData.mYSize.width,
aData.mYSize.height,
aData.mCbCrSize.width,
aData.mCbCrSize.height);
gfxASurface::gfxImageFormat format = GetOffscreenFormat();
// 'prescale' is true if the scaling is to be done as part of the
// YCbCr to RGB conversion rather than on the RGB data when rendered.
PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 &&
mScaleHint != aData.mPicSize;
if (format == gfxASurface::ImageFormatRGB16_565) {
#if defined(HAVE_YCBCR_TO_RGB565)
if (prescale &&
!gfx::IsScaleYCbCrToRGB565Fast(aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
mScaleHint.width,
mScaleHint.height,
type,
gfx::FILTER_BILINEAR) &&
gfx::IsConvertYCbCrToRGB565Fast(aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
type)) {
prescale = PR_FALSE;
}
#else
// yuv2rgb16 function not available
format = gfxASurface::ImageFormatRGB24;
#endif
}
else if (format != gfxASurface::ImageFormatRGB24) {
// No other formats are currently supported.
format = gfxASurface::ImageFormatRGB24;
}
if (format == gfxASurface::ImageFormatRGB24) {
/* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data.
See bugs 639415 and 640073. */
if (aData.mPicX != 0 || aData.mPicY != 0 || type == gfx::YV24)
prescale = PR_FALSE;
}
gfxIntSize size(prescale ? mScaleHint.width : aData.mPicSize.width,
prescale ? mScaleHint.height : aData.mPicSize.height);
gfxIntSize size(mScaleHint);
gfxUtils::GetYCbCrToRGBDestFormatAndSize(aData, format, size);
mStride = gfxASurface::FormatStrideForWidth(format, size.width);
mBuffer = AllocateBuffer(size.height * mStride);
@@ -212,71 +167,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
return;
}
// Convert from YCbCr to RGB now, scaling the image if needed.
if (size != aData.mPicSize) {
#if defined(HAVE_YCBCR_TO_RGB565)
if (format == gfxASurface::ImageFormatRGB16_565) {
gfx::ScaleYCbCrToRGB565(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
mBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
size.width,
size.height,
aData.mYStride,
aData.mCbCrStride,
mStride,
type,
gfx::FILTER_BILINEAR);
} else
#endif
gfx::ScaleYCbCrToRGB32(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
mBuffer,
aData.mPicSize.width,
aData.mPicSize.height,
size.width,
size.height,
aData.mYStride,
aData.mCbCrStride,
mStride,
type,
gfx::ROTATE_0,
gfx::FILTER_BILINEAR);
} else { // no prescale
#if defined(HAVE_YCBCR_TO_RGB565)
if (format == gfxASurface::ImageFormatRGB16_565) {
gfx::ConvertYCbCrToRGB565(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
mBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aData.mYStride,
aData.mCbCrStride,
mStride,
type);
} else // format != gfxASurface::ImageFormatRGB16_565
#endif
gfx::ConvertYCbCrToRGB32(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
mBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aData.mYStride,
aData.mCbCrStride,
mStride,
type);
}
gfxUtils::ConvertYCbCrToRGB(aData, format, size, mBuffer, mStride);
SetOffscreenFormat(format);
mSize = size;
}

View File

@@ -40,11 +40,16 @@
#include "gfxPlatform.h"
#include "gfxDrawable.h"
#include "nsRegion.h"
#include "yuv_convert.h"
#include "ycbcr_to_rgb565.h"
#ifdef XP_WIN
#include "gfxWindowsPlatform.h"
#endif
using namespace mozilla;
using namespace mozilla::layers;
static PRUint8 sUnpremultiplyTable[256*256];
static PRUint8 sPremultiplyTable[256*256];
static PRBool sTablesInitialized = PR_FALSE;
@@ -517,3 +522,136 @@ gfxUtils::GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut)
return gfxRect(aOut->x, aOut->y, aOut->width, aOut->height).IsEqualEdges(aIn);
}
void
gfxUtils::GetYCbCrToRGBDestFormatAndSize(const PlanarYCbCrImage::Data& aData,
gfxASurface::gfxImageFormat& aSuggestedFormat,
gfxIntSize& aSuggestedSize)
{
gfx::YUVType yuvtype =
gfx::TypeFromSize(aData.mYSize.width,
aData.mYSize.height,
aData.mCbCrSize.width,
aData.mCbCrSize.height);
// 'prescale' is true if the scaling is to be done as part of the
// YCbCr to RGB conversion rather than on the RGB data when rendered.
PRBool prescale = aSuggestedSize.width > 0 && aSuggestedSize.height > 0 &&
aSuggestedSize != aData.mPicSize;
if (aSuggestedFormat == gfxASurface::ImageFormatRGB16_565) {
#if defined(HAVE_YCBCR_TO_RGB565)
if (prescale &&
!gfx::IsScaleYCbCrToRGB565Fast(aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aSuggestedSize.width,
aSuggestedSize.height,
yuvtype,
gfx::FILTER_BILINEAR) &&
gfx::IsConvertYCbCrToRGB565Fast(aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
yuvtype)) {
prescale = PR_FALSE;
}
#else
// yuv2rgb16 function not available
aSuggestedFormat = gfxASurface::ImageFormatRGB24;
#endif
}
else if (aSuggestedFormat != gfxASurface::ImageFormatRGB24) {
// No other formats are currently supported.
aSuggestedFormat = gfxASurface::ImageFormatRGB24;
}
if (aSuggestedFormat == gfxASurface::ImageFormatRGB24) {
/* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data.
See bugs 639415 and 640073. */
if (aData.mPicX != 0 || aData.mPicY != 0 || yuvtype == gfx::YV24)
prescale = PR_FALSE;
}
if (!prescale) {
aSuggestedSize = aData.mPicSize;
}
}
void
gfxUtils::ConvertYCbCrToRGB(const PlanarYCbCrImage::Data& aData,
const gfxASurface::gfxImageFormat& aDestFormat,
const gfxIntSize& aDestSize,
unsigned char* aDestBuffer,
PRInt32 aStride)
{
gfx::YUVType yuvtype =
gfx::TypeFromSize(aData.mYSize.width,
aData.mYSize.height,
aData.mCbCrSize.width,
aData.mCbCrSize.height);
// Convert from YCbCr to RGB now, scaling the image if needed.
if (aDestSize != aData.mPicSize) {
#if defined(HAVE_YCBCR_TO_RGB565)
if (aDestFormat == gfxASurface::ImageFormatRGB16_565) {
gfx::ScaleYCbCrToRGB565(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
aDestBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aDestSize.width,
aDestSize.height,
aData.mYStride,
aData.mCbCrStride,
aStride,
yuvtype,
gfx::FILTER_BILINEAR);
} else
#endif
gfx::ScaleYCbCrToRGB32(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
aDestBuffer,
aData.mPicSize.width,
aData.mPicSize.height,
aDestSize.width,
aDestSize.height,
aData.mYStride,
aData.mCbCrStride,
aStride,
yuvtype,
gfx::ROTATE_0,
gfx::FILTER_BILINEAR);
} else { // no prescale
#if defined(HAVE_YCBCR_TO_RGB565)
if (aDestFormat == gfxASurface::ImageFormatRGB16_565) {
gfx::ConvertYCbCrToRGB565(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
aDestBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aData.mYStride,
aData.mCbCrStride,
aStride,
yuvtype);
} else // aDestFormat != gfxASurface::ImageFormatRGB16_565
#endif
gfx::ConvertYCbCrToRGB32(aData.mYChannel,
aData.mCbChannel,
aData.mCrChannel,
aDestBuffer,
aData.mPicX,
aData.mPicY,
aData.mPicSize.width,
aData.mPicSize.height,
aData.mYStride,
aData.mCbCrStride,
aStride,
yuvtype);
}
}

View File

@@ -41,6 +41,7 @@
#include "gfxTypes.h"
#include "gfxPattern.h"
#include "gfxImageSurface.h"
#include "ImageLayers.h"
class gfxDrawable;
class nsIntRegion;
@@ -123,6 +124,32 @@ public:
* aVal.
*/
static gfxFloat ClampToScaleFactor(gfxFloat aVal);
/**
* Helper function for ConvertYCbCrToRGB that finds the
* RGB buffer size and format for given YCbCrImage.
* @param aSuggestedFormat will be set to ImageFormatRGB24
* if the desired format is not supported.
* @param aSuggestedSize will be set to the picture size from aData
* if either the suggested size was {0,0}
* or simultaneous scaling and conversion is not supported.
*/
static void
GetYCbCrToRGBDestFormatAndSize(const mozilla::layers::PlanarYCbCrImage::Data& aData,
gfxASurface::gfxImageFormat& aSuggestedFormat,
gfxIntSize& aSuggestedSize);
/**
* Convert YCbCrImage into RGB aDestBuffer
* Format and Size parameters must have
* been passed to GetYCbCrToRGBDestFormatAndSize
*/
static void
ConvertYCbCrToRGB(const mozilla::layers::PlanarYCbCrImage::Data& aData,
const gfxASurface::gfxImageFormat& aDestFormat,
const gfxIntSize& aDestSize,
unsigned char* aDestBuffer,
PRInt32 aStride);
};
#endif