RenderMacIOSurfaceTextureHost.cpp (6407B)
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 "RenderMacIOSurfaceTextureHost.h" 8 9 #ifdef XP_MACOSX 10 # include "GLContextCGL.h" 11 #else 12 # include "GLContextEAGL.h" 13 #endif 14 15 #include "mozilla/gfx/Logging.h" 16 #include "mozilla/layers/GpuFence.h" 17 #include "mozilla/ProfilerLabels.h" 18 #include "mozilla/ProfilerMarkers.h" 19 #include "mozilla/TimeStamp.h" 20 #include "ScopedGLHelpers.h" 21 22 namespace mozilla { 23 namespace wr { 24 25 static bool CreateTextureForPlane(uint8_t aPlaneID, gl::GLContext* aGL, 26 MacIOSurface* aSurface, GLuint* aTexture) { 27 MOZ_ASSERT(aGL && aSurface && aTexture); 28 29 aGL->fGenTextures(1, aTexture); 30 ActivateBindAndTexParameteri(aGL, LOCAL_GL_TEXTURE0, 31 LOCAL_GL_TEXTURE_RECTANGLE_ARB, *aTexture); 32 aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, 33 LOCAL_GL_CLAMP_TO_EDGE); 34 aGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, 35 LOCAL_GL_CLAMP_TO_EDGE); 36 37 gfx::SurfaceFormat readFormat = gfx::SurfaceFormat::UNKNOWN; 38 bool result = aSurface->BindTexImage(aGL, aPlaneID, &readFormat); 39 // If this is a yuv format, the Webrender only supports YUY2 interleaving 40 // format. 41 MOZ_ASSERT(aSurface->GetFormat() != gfx::SurfaceFormat::YUY2 || 42 readFormat == gfx::SurfaceFormat::YUY2); 43 44 return result; 45 } 46 47 RenderMacIOSurfaceTextureHost::RenderMacIOSurfaceTextureHost( 48 MacIOSurface* aSurface, layers::GpuFence* aGpuFence) 49 : mSurface(aSurface), mGpuFence(aGpuFence), mTextureHandles{0, 0, 0} { 50 MOZ_COUNT_CTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost); 51 } 52 53 RenderMacIOSurfaceTextureHost::~RenderMacIOSurfaceTextureHost() { 54 MOZ_COUNT_DTOR_INHERITED(RenderMacIOSurfaceTextureHost, RenderTextureHost); 55 DeleteTextureHandle(); 56 } 57 58 GLuint RenderMacIOSurfaceTextureHost::GetGLHandle(uint8_t aChannelIndex) const { 59 MOZ_ASSERT(mSurface); 60 MOZ_ASSERT((mSurface->GetPlaneCount() == 0) 61 ? (aChannelIndex == mSurface->GetPlaneCount()) 62 : (aChannelIndex < mSurface->GetPlaneCount())); 63 return mTextureHandles[aChannelIndex]; 64 } 65 66 gfx::IntSize RenderMacIOSurfaceTextureHost::GetSize( 67 uint8_t aChannelIndex) const { 68 MOZ_ASSERT(mSurface); 69 MOZ_ASSERT((mSurface->GetPlaneCount() == 0) 70 ? (aChannelIndex == mSurface->GetPlaneCount()) 71 : (aChannelIndex < mSurface->GetPlaneCount())); 72 73 if (!mSurface) { 74 return gfx::IntSize(); 75 } 76 return gfx::IntSize(mSurface->GetDevicePixelWidth(aChannelIndex), 77 mSurface->GetDevicePixelHeight(aChannelIndex)); 78 } 79 80 size_t RenderMacIOSurfaceTextureHost::Bytes() { 81 return mSurface->GetAllocSize(); 82 } 83 84 wr::WrExternalImage RenderMacIOSurfaceTextureHost::Lock(uint8_t aChannelIndex, 85 gl::GLContext* aGL) { 86 if (mGL.get() != aGL) { 87 // release the texture handle in the previous gl context 88 DeleteTextureHandle(); 89 mGL = aGL; 90 mGL->MakeCurrent(); 91 } 92 93 if (!mSurface || !mGL || !mGL->MakeCurrent()) { 94 return InvalidToWrExternalImage(); 95 } 96 97 if (!mTextureHandles[0]) { 98 #ifdef XP_MACOSX 99 MOZ_ASSERT(gl::GLContextCGL::Cast(mGL.get())->GetCGLContext()); 100 #else 101 MOZ_ASSERT(gl::GLContextEAGL::Cast(mGL.get())->GetEAGLContext()); 102 #endif 103 104 // The result of GetPlaneCount() is 0 for single plane format, but it will 105 // be 2 if the format has 2 planar data. 106 CreateTextureForPlane(0, mGL, mSurface, &(mTextureHandles[0])); 107 for (size_t i = 1; i < mSurface->GetPlaneCount(); ++i) { 108 CreateTextureForPlane(i, mGL, mSurface, &(mTextureHandles[i])); 109 } 110 } 111 112 if (mGpuFence) { 113 // This timeout matches the acquisition timeout for the keyed mutex 114 // in the D3D11 texture host. 115 auto timeout = TimeDuration::FromMilliseconds(10000); 116 auto start = TimeStamp::Now(); 117 AUTO_PROFILER_MARKER("Lock MacIOSurfaceTexture", GRAPHICS); 118 while (!mGpuFence->HasCompleted() && (TimeStamp::Now() - start) < timeout) { 119 PR_Sleep(PR_MillisecondsToInterval(1)); 120 } 121 } else { 122 PROFILER_MARKER_UNTYPED("No GpuFence", GRAPHICS); 123 } 124 125 const auto size = GetSize(aChannelIndex); 126 return NativeTextureToWrExternalImage(GetGLHandle(aChannelIndex), 0.0, 0.0, 127 static_cast<float>(size.width), 128 static_cast<float>(size.height)); 129 } 130 131 void RenderMacIOSurfaceTextureHost::Unlock() {} 132 133 void RenderMacIOSurfaceTextureHost::DeleteTextureHandle() { 134 if (mTextureHandles[0] != 0 && mGL && mGL->MakeCurrent()) { 135 // Calling glDeleteTextures on 0 isn't an error. So, just make them a single 136 // call. 137 mGL->fDeleteTextures(3, mTextureHandles); 138 for (size_t i = 0; i < 3; ++i) { 139 mTextureHandles[i] = 0; 140 } 141 } 142 } 143 144 size_t RenderMacIOSurfaceTextureHost::GetPlaneCount() const { 145 size_t planeCount = mSurface->GetPlaneCount(); 146 return planeCount > 0 ? planeCount : 1; 147 } 148 149 gfx::SurfaceFormat RenderMacIOSurfaceTextureHost::GetFormat() const { 150 return mSurface->GetFormat(); 151 } 152 153 gfx::ColorDepth RenderMacIOSurfaceTextureHost::GetColorDepth() const { 154 return mSurface->GetColorDepth(); 155 } 156 157 gfx::YUVRangedColorSpace RenderMacIOSurfaceTextureHost::GetYUVColorSpace() 158 const { 159 return ToYUVRangedColorSpace(mSurface->GetYUVColorSpace(), 160 mSurface->GetColorRange()); 161 } 162 163 bool RenderMacIOSurfaceTextureHost::MapPlane(RenderCompositor* aCompositor, 164 uint8_t aChannelIndex, 165 PlaneInfo& aPlaneInfo) { 166 if (!aChannelIndex) { 167 if (NS_WARN_IF(!mSurface->Lock())) { 168 return false; 169 } 170 } 171 aPlaneInfo.mData = mSurface->GetBaseAddressOfPlane(aChannelIndex); 172 aPlaneInfo.mStride = mSurface->GetBytesPerRow(aChannelIndex); 173 aPlaneInfo.mSize = 174 gfx::IntSize(mSurface->GetDevicePixelWidth(aChannelIndex), 175 mSurface->GetDevicePixelHeight(aChannelIndex)); 176 return true; 177 } 178 179 void RenderMacIOSurfaceTextureHost::UnmapPlanes() { mSurface->Unlock(); } 180 181 } // namespace wr 182 } // namespace mozilla