|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "gfx2DGlue.h" |
|
7 |
|
8 #include "YCbCrUtils.h" |
|
9 #include "yuv_convert.h" |
|
10 #include "ycbcr_to_rgb565.h" |
|
11 |
|
12 namespace mozilla { |
|
13 namespace gfx { |
|
14 |
|
15 void |
|
16 GetYCbCrToRGBDestFormatAndSize(const layers::PlanarYCbCrData& aData, |
|
17 SurfaceFormat& aSuggestedFormat, |
|
18 IntSize& aSuggestedSize) |
|
19 { |
|
20 YUVType yuvtype = |
|
21 TypeFromSize(aData.mYSize.width, |
|
22 aData.mYSize.height, |
|
23 aData.mCbCrSize.width, |
|
24 aData.mCbCrSize.height); |
|
25 |
|
26 // 'prescale' is true if the scaling is to be done as part of the |
|
27 // YCbCr to RGB conversion rather than on the RGB data when rendered. |
|
28 bool prescale = aSuggestedSize.width > 0 && aSuggestedSize.height > 0 && |
|
29 aSuggestedSize != aData.mPicSize; |
|
30 |
|
31 if (aSuggestedFormat == SurfaceFormat::R5G6B5) { |
|
32 #if defined(HAVE_YCBCR_TO_RGB565) |
|
33 if (prescale && |
|
34 !IsScaleYCbCrToRGB565Fast(aData.mPicX, |
|
35 aData.mPicY, |
|
36 aData.mPicSize.width, |
|
37 aData.mPicSize.height, |
|
38 aSuggestedSize.width, |
|
39 aSuggestedSize.height, |
|
40 yuvtype, |
|
41 FILTER_BILINEAR) && |
|
42 IsConvertYCbCrToRGB565Fast(aData.mPicX, |
|
43 aData.mPicY, |
|
44 aData.mPicSize.width, |
|
45 aData.mPicSize.height, |
|
46 yuvtype)) { |
|
47 prescale = false; |
|
48 } |
|
49 #else |
|
50 // yuv2rgb16 function not available |
|
51 aSuggestedFormat = SurfaceFormat::B8G8R8X8; |
|
52 #endif |
|
53 } |
|
54 else if (aSuggestedFormat != SurfaceFormat::B8G8R8X8) { |
|
55 // No other formats are currently supported. |
|
56 aSuggestedFormat = SurfaceFormat::B8G8R8X8; |
|
57 } |
|
58 if (aSuggestedFormat == SurfaceFormat::B8G8R8X8) { |
|
59 /* ScaleYCbCrToRGB32 does not support a picture offset, nor 4:4:4 data. |
|
60 See bugs 639415 and 640073. */ |
|
61 if (aData.mPicX != 0 || aData.mPicY != 0 || yuvtype == YV24) |
|
62 prescale = false; |
|
63 } |
|
64 if (!prescale) { |
|
65 aSuggestedSize = aData.mPicSize; |
|
66 } |
|
67 } |
|
68 |
|
69 void |
|
70 ConvertYCbCrToRGB(const layers::PlanarYCbCrData& aData, |
|
71 const SurfaceFormat& aDestFormat, |
|
72 const IntSize& aDestSize, |
|
73 unsigned char* aDestBuffer, |
|
74 int32_t aStride) |
|
75 { |
|
76 // ConvertYCbCrToRGB et al. assume the chroma planes are rounded up if the |
|
77 // luma plane is odd sized. |
|
78 MOZ_ASSERT((aData.mCbCrSize.width == aData.mYSize.width || |
|
79 aData.mCbCrSize.width == (aData.mYSize.width + 1) >> 1) && |
|
80 (aData.mCbCrSize.height == aData.mYSize.height || |
|
81 aData.mCbCrSize.height == (aData.mYSize.height + 1) >> 1)); |
|
82 YUVType yuvtype = |
|
83 TypeFromSize(aData.mYSize.width, |
|
84 aData.mYSize.height, |
|
85 aData.mCbCrSize.width, |
|
86 aData.mCbCrSize.height); |
|
87 |
|
88 // Convert from YCbCr to RGB now, scaling the image if needed. |
|
89 if (aDestSize != aData.mPicSize) { |
|
90 #if defined(HAVE_YCBCR_TO_RGB565) |
|
91 if (aDestFormat == SurfaceFormat::R5G6B5) { |
|
92 ScaleYCbCrToRGB565(aData.mYChannel, |
|
93 aData.mCbChannel, |
|
94 aData.mCrChannel, |
|
95 aDestBuffer, |
|
96 aData.mPicX, |
|
97 aData.mPicY, |
|
98 aData.mPicSize.width, |
|
99 aData.mPicSize.height, |
|
100 aDestSize.width, |
|
101 aDestSize.height, |
|
102 aData.mYStride, |
|
103 aData.mCbCrStride, |
|
104 aStride, |
|
105 yuvtype, |
|
106 FILTER_BILINEAR); |
|
107 } else |
|
108 #endif |
|
109 ScaleYCbCrToRGB32(aData.mYChannel, // |
|
110 aData.mCbChannel, |
|
111 aData.mCrChannel, |
|
112 aDestBuffer, |
|
113 aData.mPicSize.width, |
|
114 aData.mPicSize.height, |
|
115 aDestSize.width, |
|
116 aDestSize.height, |
|
117 aData.mYStride, |
|
118 aData.mCbCrStride, |
|
119 aStride, |
|
120 yuvtype, |
|
121 ROTATE_0, |
|
122 FILTER_BILINEAR); |
|
123 } else { // no prescale |
|
124 #if defined(HAVE_YCBCR_TO_RGB565) |
|
125 if (aDestFormat == SurfaceFormat::R5G6B5) { |
|
126 ConvertYCbCrToRGB565(aData.mYChannel, |
|
127 aData.mCbChannel, |
|
128 aData.mCrChannel, |
|
129 aDestBuffer, |
|
130 aData.mPicX, |
|
131 aData.mPicY, |
|
132 aData.mPicSize.width, |
|
133 aData.mPicSize.height, |
|
134 aData.mYStride, |
|
135 aData.mCbCrStride, |
|
136 aStride, |
|
137 yuvtype); |
|
138 } else // aDestFormat != gfxImageFormat::RGB16_565 |
|
139 #endif |
|
140 ConvertYCbCrToRGB32(aData.mYChannel, // |
|
141 aData.mCbChannel, |
|
142 aData.mCrChannel, |
|
143 aDestBuffer, |
|
144 aData.mPicX, |
|
145 aData.mPicY, |
|
146 aData.mPicSize.width, |
|
147 aData.mPicSize.height, |
|
148 aData.mYStride, |
|
149 aData.mCbCrStride, |
|
150 aStride, |
|
151 yuvtype); |
|
152 } |
|
153 } |
|
154 |
|
155 } |
|
156 } |