Bug 1691109 [wpt PR 27513] - Increase timeout duration for wpt/fetch/api/basic/keepal...
[gecko.git] / gfx / layers / MacIOSurfaceImage.cpp
blob8a155bc5cc7cda5009330995e59468c7c549578c
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/. */
7 #include "MacIOSurfaceHelpers.h"
8 #include "MacIOSurfaceImage.h"
9 #include "gfxPlatform.h"
10 #include "mozilla/layers/CompositableClient.h"
11 #include "mozilla/layers/CompositableForwarder.h"
12 #include "mozilla/layers/MacIOSurfaceTextureClientOGL.h"
13 #include "mozilla/layers/TextureForwarder.h"
14 #include "mozilla/StaticPrefs_layers.h"
15 #include "mozilla/UniquePtr.h"
16 #include "YCbCrUtils.h"
18 using namespace mozilla::layers;
19 using namespace mozilla::gfx;
21 TextureClient* MacIOSurfaceImage::GetTextureClient(
22 KnowsCompositor* aKnowsCompositor) {
23 if (!mTextureClient) {
24 BackendType backend = BackendType::NONE;
25 mTextureClient = TextureClient::CreateWithData(
26 MacIOSurfaceTextureData::Create(mSurface, backend),
27 TextureFlags::DEFAULT, aKnowsCompositor->GetTextureForwarder());
29 return mTextureClient;
32 already_AddRefed<SourceSurface> MacIOSurfaceImage::GetAsSourceSurface() {
33 return CreateSourceSurfaceFromMacIOSurface(mSurface);
36 bool MacIOSurfaceImage::SetData(ImageContainer* aContainer,
37 const PlanarYCbCrData& aData) {
38 MOZ_ASSERT(!mSurface);
40 if (aData.mYSkip != 0 || aData.mCbSkip != 0 || aData.mCrSkip != 0 ||
41 !(aData.mYUVColorSpace == YUVColorSpace::BT601 ||
42 aData.mYUVColorSpace == YUVColorSpace::BT709) ||
43 !(aData.mColorRange == ColorRange::FULL ||
44 aData.mColorRange == ColorRange::LIMITED) ||
45 aData.mColorDepth != ColorDepth::COLOR_8) {
46 return false;
49 if (aData.mCbCrSize.width * 2 != aData.mYSize.width) {
50 return false;
53 // We can only support 4:2:2 and 4:2:0 formats currently.
54 if (aData.mCbCrSize.height != aData.mYSize.height &&
55 aData.mCbCrSize.height * 2 != aData.mYSize.height) {
56 return false;
59 RefPtr<MacIOSurfaceRecycleAllocator> allocator =
60 aContainer->GetMacIOSurfaceRecycleAllocator();
62 RefPtr<MacIOSurface> surf = allocator->Allocate(
63 aData.mYSize, aData.mCbCrSize, aData.mYUVColorSpace, aData.mColorRange);
65 surf->Lock(false);
67 // If the CbCrSize's height is half of the YSize's height, then we'll
68 // need to duplicate the CbCr data on every second row.
69 size_t heightScale = aData.mYSize.height / aData.mCbCrSize.height;
71 MOZ_ASSERT(surf->GetFormat() == SurfaceFormat::YUV422);
73 // The underlying IOSurface has format kCVPixelFormatType_422YpCbCr8FullRange
74 // or kCVPixelFormatType_422YpCbCr8_yuvs, which uses a 4:2:2 Y`0 Cb Y`1 Cr
75 // layout. See CVPixelBuffer.h for the full list of format descriptions.
76 MOZ_ASSERT(aData.mYSize.height > 0);
77 uint8_t* dst = (uint8_t*)surf->GetBaseAddressOfPlane(0);
78 size_t stride = surf->GetBytesPerRow(0);
79 for (size_t i = 0; i < (size_t)aData.mYSize.height; i++) {
80 // Compute the row addresses. If the input was 4:2:0, then
81 // we divide i by 2, so that each source row of CbCr maps to
82 // two dest rows.
83 uint8_t* rowYSrc = aData.mYChannel + aData.mYStride * i;
84 uint8_t* rowCbSrc =
85 aData.mCbChannel + aData.mCbCrStride * (i / heightScale);
86 uint8_t* rowCrSrc =
87 aData.mCrChannel + aData.mCbCrStride * (i / heightScale);
88 uint8_t* rowDst = dst + stride * i;
90 // Iterate across the CbCr width (which we have guaranteed to be half of
91 // the surface width), and write two 16bit pixels each time.
92 for (size_t j = 0; j < (size_t)aData.mCbCrSize.width; j++) {
93 *rowDst = *rowYSrc;
94 rowDst++;
95 rowYSrc++;
97 *rowDst = *rowCbSrc;
98 rowDst++;
99 rowCbSrc++;
101 *rowDst = *rowYSrc;
102 rowDst++;
103 rowYSrc++;
105 *rowDst = *rowCrSrc;
106 rowDst++;
107 rowCrSrc++;
111 surf->Unlock(false);
112 mSurface = surf;
113 mPictureRect = aData.GetPictureRect();
114 return true;
117 already_AddRefed<MacIOSurface> MacIOSurfaceRecycleAllocator::Allocate(
118 const gfx::IntSize aYSize, const gfx::IntSize& aCbCrSize,
119 gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange) {
120 nsTArray<CFTypeRefPtr<IOSurfaceRef>> surfaces = std::move(mSurfaces);
121 RefPtr<MacIOSurface> result;
122 for (auto& surf : surfaces) {
123 // If the surface size has changed, then discard any surfaces of the old
124 // size.
125 if (::IOSurfaceGetWidthOfPlane(surf.get(), 0) != (size_t)aYSize.width ||
126 ::IOSurfaceGetHeightOfPlane(surf.get(), 0) != (size_t)aYSize.height) {
127 continue;
130 // Only construct a MacIOSurface object when we find one that isn't
131 // in-use, since the constructor adds a usage ref.
132 if (!result && !::IOSurfaceIsInUse(surf.get())) {
133 result = new MacIOSurface(surf, 1.0, false, aYUVColorSpace);
136 mSurfaces.AppendElement(surf);
139 if (!result) {
140 result =
141 MacIOSurface::CreateYUV422Surface(aYSize, aYUVColorSpace, aColorRange);
143 if (mSurfaces.Length() <
144 StaticPrefs::layers_iosurfaceimage_recycle_limit()) {
145 mSurfaces.AppendElement(result->GetIOSurfaceRef());
149 return result.forget();