Bug 686742 - Move YUV conversion code into gfxUtil functions. r=derf
This commit is contained in:
@@ -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 {
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user