mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1750858 - Respect mPicSize in WebRender. r=sotaro
This makes WR properly handle mPicSize when RenderBufferTextureHost is used. The main change is that we need to take care to pass in display().Size() from the descriptor, and then further use that to carefully limit the size of the CbCr texture, as it doesn't necessarily maintain an appropriate half-sized scale with respect to the Y texture if it is padded. Given that mPicSize should now actually work, we should no longer need any of the previous mCroppedSize mechanisms that were added to work around this, and so they are removed in this patch. Differential Revision: https://phabricator.services.mozilla.com/D139267
This commit is contained in:
parent
f38fa1efe5
commit
9ff6a3947e
@ -542,8 +542,6 @@ FFmpegVideoDecoder<LIBAV_VER>::CreateEmptyPlanarYCbCrData(
|
||||
&paddedYSize.height);
|
||||
data.mYSize = gfx::IntSize{paddedYSize.Width(), paddedYSize.Height()};
|
||||
data.mYStride = data.mYSize.Width() * bytesPerChannel;
|
||||
data.mCroppedYSize = Some(
|
||||
gfx::IntSize{aCodecContext->coded_width, aCodecContext->coded_height});
|
||||
|
||||
MOZ_ASSERT(
|
||||
IsColorFormatSupportedForUsingCustomizedBuffer(aCodecContext->pix_fmt));
|
||||
@ -560,7 +558,6 @@ FFmpegVideoDecoder<LIBAV_VER>::CreateEmptyPlanarYCbCrData(
|
||||
data.mCbCrSize =
|
||||
gfx::IntSize{paddedCbCrSize.Width(), paddedCbCrSize.Height()};
|
||||
data.mCbCrStride = data.mCbCrSize.Width() * bytesPerChannel;
|
||||
data.mCroppedCbCrSize = Some(gfx::IntSize{uvDims.Width(), uvDims.Height()});
|
||||
|
||||
// Setting other attributes
|
||||
data.mPicSize =
|
||||
@ -585,9 +582,8 @@ FFmpegVideoDecoder<LIBAV_VER>::CreateEmptyPlanarYCbCrData(
|
||||
"Created plane data, YSize=(%d, %d), CbCrSize=(%d, %d), "
|
||||
"CroppedYSize=(%d, %d), CroppedCbCrSize=(%d, %d), ColorDepth=%hhu",
|
||||
data.mYSize.Width(), data.mYSize.Height(), data.mCbCrSize.Width(),
|
||||
data.mCbCrSize.Height(), data.mCroppedYSize->Width(),
|
||||
data.mCroppedYSize->Height(), data.mCroppedCbCrSize->Width(),
|
||||
data.mCroppedCbCrSize->Height(), static_cast<uint8_t>(data.mColorDepth));
|
||||
data.mCbCrSize.Height(), data.mPicSize.Width(), data.mPicSize.Height(),
|
||||
uvDims.Width(), uvDims.Height(), static_cast<uint8_t>(data.mColorDepth));
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -95,15 +95,8 @@ class ShmemTextureData : public BufferTextureData {
|
||||
|
||||
virtual size_t GetBufferSize() override { return mShmem.Size<uint8_t>(); }
|
||||
|
||||
bool CropYCbCrPlanes(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize) override;
|
||||
|
||||
// Restore original descriptor that might be changed by CropYCbCrPlanes();
|
||||
void RestoreOriginalDescriptor() override;
|
||||
|
||||
protected:
|
||||
mozilla::ipc::Shmem mShmem;
|
||||
Maybe<BufferDescriptor> mOrigDescriptor;
|
||||
};
|
||||
|
||||
BufferTextureData* BufferTextureData::Create(
|
||||
@ -517,38 +510,5 @@ void ShmemTextureData::Deallocate(LayersIPCChannel* aAllocator) {
|
||||
aAllocator->DeallocShmem(mShmem);
|
||||
}
|
||||
|
||||
bool ShmemTextureData::CropYCbCrPlanes(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize) {
|
||||
if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& current = mDescriptor.get_YCbCrDescriptor();
|
||||
if (current.ySize() < aYSize || current.cbCrSize() < aCbCrSize) {
|
||||
NS_WARNING("Cropped size should not exceed the original size!");
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mOrigDescriptor.isNothing());
|
||||
// Store original descriptor.
|
||||
mOrigDescriptor = Some(current);
|
||||
|
||||
auto newDescritor = YCbCrDescriptor(
|
||||
current.display(), aYSize, current.yStride(), aCbCrSize,
|
||||
current.cbCrStride(), current.yOffset(), current.cbOffset(),
|
||||
current.crOffset(), current.stereoMode(), current.colorDepth(),
|
||||
current.yUVColorSpace(), current.colorRange());
|
||||
mDescriptor = BufferDescriptor(newDescritor);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShmemTextureData::RestoreOriginalDescriptor() {
|
||||
if (mOrigDescriptor.isNothing()) {
|
||||
return;
|
||||
}
|
||||
mDescriptor = mOrigDescriptor.ref();
|
||||
mOrigDescriptor = Nothing();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -661,12 +661,6 @@ struct PlanarYCbCrData {
|
||||
}
|
||||
|
||||
static Maybe<PlanarYCbCrData> From(const SurfaceDescriptorBuffer&);
|
||||
|
||||
// We would use mPicSize, but that's not hooked up in WR for RawData
|
||||
// ExternalImages, so we manually clip sizes later on. We should fix WR,
|
||||
// but not in this patch. Do not use unless mPicSize doesn't work for you.
|
||||
Maybe<gfx::IntSize> mCroppedYSize;
|
||||
Maybe<gfx::IntSize> mCroppedCbCrSize;
|
||||
};
|
||||
|
||||
// This type is currently only used for AVIF and therefore makes some
|
||||
|
@ -345,6 +345,11 @@ void ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
|
||||
aStride);
|
||||
}
|
||||
|
||||
gfx::IntSize GetCroppedCbCrSize(const YCbCrDescriptor& aDescriptor) {
|
||||
return gfx::GetCroppedCbCrSize(aDescriptor.ySize(), aDescriptor.cbCrSize(),
|
||||
aDescriptor.display().Size());
|
||||
}
|
||||
|
||||
} // namespace ImageDataSerializer
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -100,6 +100,8 @@ void ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
|
||||
unsigned char* aDestBuffer,
|
||||
int32_t aStride);
|
||||
|
||||
gfx::IntSize GetCroppedCbCrSize(const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
} // namespace ImageDataSerializer
|
||||
|
||||
} // namespace layers
|
||||
|
@ -850,14 +850,6 @@ bool TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) {
|
||||
return mData ? mData->Serialize(aOutDescriptor) : false;
|
||||
}
|
||||
|
||||
bool TextureClient::CropYCbCrPlanes(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize) {
|
||||
if (!mData) {
|
||||
return false;
|
||||
}
|
||||
return mData->CropYCbCrPlanes(aYSize, aCbCrSize);
|
||||
}
|
||||
|
||||
// static
|
||||
PTextureChild* TextureClient::CreateIPDLActor() {
|
||||
TextureChild* c = new TextureChild();
|
||||
|
@ -307,17 +307,6 @@ class TextureData {
|
||||
return mozilla::ipc::FileDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crop YCbCr planes to a smaller size. An use case is that we would need to
|
||||
* allocate a larger size for planes in order to meet the special alignement
|
||||
* requirement (eg. for ffmpeg video decoding), but crop planes to a correct
|
||||
* range after allocation is done.
|
||||
*/
|
||||
virtual bool CropYCbCrPlanes(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DEFAULT_CTOR(TextureData)
|
||||
};
|
||||
@ -480,15 +469,6 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
|
||||
bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect,
|
||||
const gfx::IntPoint* aPoint);
|
||||
|
||||
/**
|
||||
* Crop YCbCr planes to a smaller size. An use case is that we would need to
|
||||
* allocate a larger size for planes in order to meet the special alignement
|
||||
* requirement (eg. for ffmpeg video decoding), but crop planes to a correct
|
||||
* range after allocation is done.
|
||||
*/
|
||||
bool CropYCbCrPlanes(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize);
|
||||
|
||||
/**
|
||||
* Allocate and deallocate a TextureChild actor.
|
||||
*
|
||||
|
@ -529,11 +529,12 @@ void BufferTextureHost::PushResourceUpdates(
|
||||
MOZ_ASSERT(aImageKeys.length() == 3);
|
||||
|
||||
const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
|
||||
gfx::IntSize ySize = desc.display().Size();
|
||||
gfx::IntSize cbcrSize = ImageDataSerializer::GetCroppedCbCrSize(desc);
|
||||
wr::ImageDescriptor yDescriptor(
|
||||
desc.ySize(), desc.yStride(),
|
||||
SurfaceFormatForColorDepth(desc.colorDepth()));
|
||||
ySize, desc.yStride(), SurfaceFormatForColorDepth(desc.colorDepth()));
|
||||
wr::ImageDescriptor cbcrDescriptor(
|
||||
desc.cbCrSize(), desc.cbCrStride(),
|
||||
cbcrSize, desc.cbCrStride(),
|
||||
SurfaceFormatForColorDepth(desc.colorDepth()));
|
||||
(aResources.*method)(aImageKeys[0], yDescriptor, aExtID, imageType, 0);
|
||||
(aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, imageType, 1);
|
||||
|
@ -132,18 +132,6 @@ bool SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::IntSize imageYSize =
|
||||
aData.mCroppedYSize ? *aData.mCroppedYSize : aData.mYSize;
|
||||
gfx::IntSize imageCbCrSize =
|
||||
aData.mCroppedCbCrSize ? *aData.mCroppedCbCrSize : aData.mCbCrSize;
|
||||
if (aData.mCroppedYSize || aData.mCroppedCbCrSize) {
|
||||
// If cropping fails, then reset Y&CbCr sizes to non-cropped sizes.
|
||||
if (!mTextureClient->CropYCbCrPlanes(imageYSize, imageCbCrSize)) {
|
||||
imageYSize = aData.mYSize;
|
||||
imageCbCrSize = aData.mCbCrSize;
|
||||
}
|
||||
}
|
||||
|
||||
MappedYCbCrTextureData mapped;
|
||||
// The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls
|
||||
// pointers out of the TextureClient and keeps them around, which works only
|
||||
@ -163,8 +151,8 @@ bool SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) {
|
||||
mData.mYChannel = aData.mYChannel;
|
||||
mData.mCbChannel = aData.mCbChannel;
|
||||
mData.mCrChannel = aData.mCrChannel;
|
||||
mData.mYSize = imageYSize;
|
||||
mData.mCbCrSize = imageCbCrSize;
|
||||
mData.mYSize = aData.mYSize;
|
||||
mData.mCbCrSize = aData.mCbCrSize;
|
||||
mData.mPicX = aData.mPicX;
|
||||
mData.mPicY = aData.mPicY;
|
||||
mData.mPicSize = aData.mPicSize;
|
||||
|
@ -208,19 +208,21 @@ bool RenderBufferTextureHost::MapPlane(RenderCompositor* aCompositor,
|
||||
aPlaneInfo.mData =
|
||||
layers::ImageDataSerializer::GetYChannel(mBuffer, desc);
|
||||
aPlaneInfo.mStride = desc.yStride();
|
||||
aPlaneInfo.mSize = desc.ySize();
|
||||
aPlaneInfo.mSize = desc.display().Size();
|
||||
break;
|
||||
case 1:
|
||||
aPlaneInfo.mData =
|
||||
layers::ImageDataSerializer::GetCbChannel(mBuffer, desc);
|
||||
aPlaneInfo.mStride = desc.cbCrStride();
|
||||
aPlaneInfo.mSize = desc.cbCrSize();
|
||||
aPlaneInfo.mSize =
|
||||
layers::ImageDataSerializer::GetCroppedCbCrSize(desc);
|
||||
break;
|
||||
case 2:
|
||||
aPlaneInfo.mData =
|
||||
layers::ImageDataSerializer::GetCrChannel(mBuffer, desc);
|
||||
aPlaneInfo.mStride = desc.cbCrStride();
|
||||
aPlaneInfo.mSize = desc.cbCrSize();
|
||||
aPlaneInfo.mSize =
|
||||
layers::ImageDataSerializer::GetCroppedCbCrSize(desc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -17,16 +17,40 @@ namespace gfx {
|
||||
|
||||
// clang-format off
|
||||
|
||||
IntSize GetCroppedCbCrSize(const IntSize& aYSize,
|
||||
const IntSize& aCbCrSize,
|
||||
const IntSize& aDisplaySize) {
|
||||
// The supplied ySize and cbcrSize are dimensions that may be padded for
|
||||
// alignment. display holds the intended cropped display size of the data.
|
||||
// The ySize can simply be limited by the display size. The cbcrSize must
|
||||
// be cropped by checking if the uncropped size is approximately half, and
|
||||
// then halving the cropped ySize since the uncropped sizes may be padded
|
||||
// inconsistently.
|
||||
IntSize croppedCbCrSize = Min(aDisplaySize, aCbCrSize);
|
||||
if (aCbCrSize.height < aYSize.height &&
|
||||
aCbCrSize.height >= aYSize.height / 2) {
|
||||
croppedCbCrSize.width = (aDisplaySize.width + 1) / 2;
|
||||
croppedCbCrSize.height = (aDisplaySize.height + 1) / 2;
|
||||
} else if (aCbCrSize.width < aYSize.width &&
|
||||
aCbCrSize.width >= aYSize.width / 2) {
|
||||
croppedCbCrSize.width = (aDisplaySize.width + 1) / 2;
|
||||
}
|
||||
return croppedCbCrSize;
|
||||
}
|
||||
|
||||
static YUVType GetYUVType(const layers::PlanarYCbCrData& aData) {
|
||||
IntSize croppedCbCrSize =
|
||||
GetCroppedCbCrSize(aData.mYSize, aData.mCbCrSize, aData.mPicSize);
|
||||
return TypeFromSize(aData.mPicSize.width, aData.mPicSize.height,
|
||||
croppedCbCrSize.width, croppedCbCrSize.height);
|
||||
}
|
||||
|
||||
void
|
||||
GetYCbCrToRGBDestFormatAndSize(const layers::PlanarYCbCrData& aData,
|
||||
SurfaceFormat& aSuggestedFormat,
|
||||
IntSize& aSuggestedSize)
|
||||
{
|
||||
YUVType yuvtype =
|
||||
TypeFromSize(aData.mYSize.width,
|
||||
aData.mYSize.height,
|
||||
aData.mCbCrSize.width,
|
||||
aData.mCbCrSize.height);
|
||||
YUVType yuvtype = GetYUVType(aData);
|
||||
|
||||
// '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.
|
||||
@ -109,12 +133,7 @@ ConvertYCbCrToRGBInternal(const layers::PlanarYCbCrData& aData,
|
||||
{
|
||||
// ConvertYCbCrToRGB et al. assume the chroma planes are rounded up if the
|
||||
// luma plane is odd sized. Monochrome images have 0-sized CbCr planes
|
||||
MOZ_ASSERT(aData.mCbCrSize.width == aData.mYSize.width ||
|
||||
aData.mCbCrSize.width == (aData.mYSize.width + 1) >> 1 ||
|
||||
aData.mCbCrSize.width == 0);
|
||||
MOZ_ASSERT(aData.mCbCrSize.height == aData.mYSize.height ||
|
||||
aData.mCbCrSize.height == (aData.mYSize.height + 1) >> 1 ||
|
||||
aData.mCbCrSize.height == 0);
|
||||
YUVType yuvtype = GetYUVType(aData);
|
||||
|
||||
// Used if converting to 8 bits YUV.
|
||||
UniquePtr<uint8_t[]> yChannel;
|
||||
@ -185,12 +204,6 @@ ConvertYCbCrToRGBInternal(const layers::PlanarYCbCrData& aData,
|
||||
}
|
||||
}
|
||||
|
||||
YUVType yuvtype =
|
||||
TypeFromSize(srcData.mYSize.width,
|
||||
srcData.mYSize.height,
|
||||
srcData.mCbCrSize.width,
|
||||
srcData.mCbCrSize.height);
|
||||
|
||||
// Convert from YCbCr to RGB now, scaling the image if needed.
|
||||
if (aDestSize != srcData.mPicSize) {
|
||||
#if defined(HAVE_YCBCR_TO_RGB565)
|
||||
|
@ -12,6 +12,9 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
IntSize GetCroppedCbCrSize(const IntSize& aYSize, const IntSize& aCbCrSize,
|
||||
const IntSize& aDisplaySize);
|
||||
|
||||
void
|
||||
GetYCbCrToRGBDestFormatAndSize(const layers::PlanarYCbCrData& aData,
|
||||
SurfaceFormat& aSuggestedFormat,
|
||||
|
Loading…
Reference in New Issue
Block a user