Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "SurfacePipe.h"
8 :
9 : #include <utility>
10 :
11 : #include "mozilla/ClearOnShutdown.h"
12 : #include "mozilla/DebugOnly.h"
13 : #include "Decoder.h"
14 :
15 : namespace mozilla {
16 : namespace image {
17 :
18 : using namespace gfx;
19 :
20 : using std::min;
21 :
22 3 : /* static */ UniquePtr<NullSurfaceSink> NullSurfaceSink::sSingleton;
23 :
24 : /* static */ NullSurfaceSink*
25 310 : NullSurfaceSink::Singleton()
26 : {
27 310 : if (!sSingleton) {
28 3 : MOZ_ASSERT(NS_IsMainThread());
29 3 : sSingleton = MakeUnique<NullSurfaceSink>();
30 3 : ClearOnShutdown(&sSingleton);
31 :
32 6 : DebugOnly<nsresult> rv = sSingleton->Configure(NullSurfaceConfig { });
33 3 : MOZ_ASSERT(NS_SUCCEEDED(rv), "Couldn't configure a NullSurfaceSink?");
34 : }
35 :
36 310 : return sSingleton.get();
37 : }
38 :
39 : nsresult
40 3 : NullSurfaceSink::Configure(const NullSurfaceConfig& aConfig)
41 : {
42 : // Note that the choice of uint32_t as the pixel size here is more or less
43 : // arbitrary, since you cannot write to a NullSurfaceSink anyway, but uint32_t
44 : // is a natural choice since most SurfacePipes will be for BGRA/BGRX surfaces.
45 3 : ConfigureFilter(IntSize(), sizeof(uint32_t));
46 3 : return NS_OK;
47 : }
48 :
49 : Maybe<SurfaceInvalidRect>
50 1538 : AbstractSurfaceSink::TakeInvalidRect()
51 : {
52 1538 : if (mInvalidRect.IsEmpty()) {
53 0 : return Nothing();
54 : }
55 :
56 1538 : SurfaceInvalidRect invalidRect;
57 1538 : invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect;
58 :
59 : // Forget about the invalid rect we're returning.
60 1538 : mInvalidRect = IntRect();
61 :
62 1538 : return Some(invalidRect);
63 : }
64 :
65 : uint8_t*
66 48 : AbstractSurfaceSink::DoResetToFirstRow()
67 : {
68 48 : mRow = 0;
69 48 : return GetRowPointer();
70 : }
71 :
72 : uint8_t*
73 1543 : AbstractSurfaceSink::DoAdvanceRow()
74 : {
75 1543 : if (mRow >= uint32_t(InputSize().height)) {
76 0 : return nullptr;
77 : }
78 :
79 : // If we're vertically flipping the output, we need to flip the invalid rect. Since we're
80 : // dealing with an axis-aligned rect, only the y coordinate needs to change.
81 1543 : int32_t invalidY = mFlipVertically
82 4629 : ? InputSize().height - (mRow + 1)
83 4629 : : mRow;
84 1542 : mInvalidRect.UnionRect(mInvalidRect,
85 3085 : IntRect(0, invalidY, InputSize().width, 1));
86 :
87 1542 : mRow = min(uint32_t(InputSize().height), mRow + 1);
88 :
89 3084 : return mRow < uint32_t(InputSize().height) ? GetRowPointer()
90 1542 : : nullptr;
91 : }
92 :
93 : nsresult
94 48 : SurfaceSink::Configure(const SurfaceConfig& aConfig)
95 : {
96 : // For non-paletted surfaces, the surface size is just the output size.
97 48 : IntSize surfaceSize = aConfig.mOutputSize;
98 :
99 : // Non-paletted surfaces should not have frame rects, so we just pass
100 : // AllocateFrame() a frame rect which covers the entire surface.
101 48 : IntRect frameRect(0, 0, surfaceSize.width, surfaceSize.height);
102 :
103 : // Allocate the frame.
104 : // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
105 : // to allocate the frame directly here and get rid of Decoder::AllocateFrame
106 : // altogether.
107 48 : nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
108 : surfaceSize,
109 : frameRect,
110 96 : aConfig.mFormat);
111 48 : if (NS_FAILED(rv)) {
112 0 : return rv;
113 : }
114 :
115 48 : mImageData = aConfig.mDecoder->mImageData;
116 48 : mImageDataLength = aConfig.mDecoder->mImageDataLength;
117 48 : mFlipVertically = aConfig.mFlipVertically;
118 :
119 48 : MOZ_ASSERT(mImageData);
120 48 : MOZ_ASSERT(mImageDataLength ==
121 : uint32_t(surfaceSize.width * surfaceSize.height * sizeof(uint32_t)));
122 :
123 48 : ConfigureFilter(surfaceSize, sizeof(uint32_t));
124 48 : return NS_OK;
125 : }
126 :
127 : uint8_t*
128 1542 : SurfaceSink::GetRowPointer() const
129 : {
130 : // If we're flipping vertically, reverse the order in which we traverse the
131 : // rows.
132 1542 : uint32_t row = mFlipVertically
133 3084 : ? InputSize().height - (mRow + 1)
134 3084 : : mRow;
135 :
136 1542 : uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint32_t);
137 :
138 1542 : MOZ_ASSERT(rowPtr >= mImageData);
139 1542 : MOZ_ASSERT(rowPtr < mImageData + mImageDataLength);
140 1542 : MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint32_t) <=
141 : mImageData + mImageDataLength);
142 :
143 1542 : return rowPtr;
144 : }
145 :
146 :
147 : nsresult
148 0 : PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig)
149 : {
150 0 : MOZ_ASSERT(aConfig.mFormat == SurfaceFormat::B8G8R8A8);
151 :
152 : // For paletted surfaces, the surface size is the size of the frame rect.
153 0 : IntSize surfaceSize = aConfig.mFrameRect.Size();
154 :
155 : // Allocate the frame.
156 : // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
157 : // to allocate the frame directly here and get rid of Decoder::AllocateFrame
158 : // altogether.
159 0 : nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
160 : aConfig.mOutputSize,
161 : aConfig.mFrameRect,
162 0 : aConfig.mFormat,
163 0 : aConfig.mPaletteDepth);
164 0 : if (NS_FAILED(rv)) {
165 0 : return rv;
166 : }
167 :
168 0 : mImageData = aConfig.mDecoder->mImageData;
169 0 : mImageDataLength = aConfig.mDecoder->mImageDataLength;
170 0 : mFlipVertically = aConfig.mFlipVertically;
171 0 : mFrameRect = aConfig.mFrameRect;
172 :
173 0 : MOZ_ASSERT(mImageData);
174 0 : MOZ_ASSERT(mImageDataLength ==
175 : uint32_t(mFrameRect.width * mFrameRect.height * sizeof(uint8_t)));
176 :
177 0 : ConfigureFilter(surfaceSize, sizeof(uint8_t));
178 0 : return NS_OK;
179 : }
180 :
181 : uint8_t*
182 0 : PalettedSurfaceSink::GetRowPointer() const
183 : {
184 : // If we're flipping vertically, reverse the order in which we traverse the
185 : // rows.
186 0 : uint32_t row = mFlipVertically
187 0 : ? InputSize().height - (mRow + 1)
188 0 : : mRow;
189 :
190 0 : uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint8_t);
191 :
192 0 : MOZ_ASSERT(rowPtr >= mImageData);
193 0 : MOZ_ASSERT(rowPtr < mImageData + mImageDataLength);
194 0 : MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint8_t) <=
195 : mImageData + mImageDataLength);
196 :
197 0 : return rowPtr;
198 : }
199 :
200 : } // namespace image
201 : } // namespace mozilla
|