RenderExternalTextureHost.cpp (7841B)
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 "RenderExternalTextureHost.h" 8 9 #include "mozilla/gfx/Logging.h" 10 #include "mozilla/layers/ImageDataSerializer.h" 11 12 #include "GLContext.h" 13 14 namespace mozilla { 15 namespace wr { 16 17 RenderExternalTextureHost::RenderExternalTextureHost( 18 uint8_t* aBuffer, const layers::BufferDescriptor& aDescriptor) 19 : mBuffer(aBuffer), 20 mDescriptor(aDescriptor), 21 mInitialized(false), 22 mTextureUpdateNeeded(true) { 23 MOZ_COUNT_CTOR_INHERITED(RenderExternalTextureHost, RenderTextureHost); 24 25 switch (mDescriptor.type()) { 26 case layers::BufferDescriptor::TYCbCrDescriptor: { 27 const layers::YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor(); 28 mSize = ycbcr.display().Size(); 29 mFormat = gfx::SurfaceFormat::YUV420; 30 break; 31 } 32 case layers::BufferDescriptor::TRGBDescriptor: { 33 const layers::RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); 34 mSize = rgb.size(); 35 mFormat = rgb.format(); 36 break; 37 } 38 default: 39 gfxCriticalError() << "Bad buffer host descriptor " 40 << (int)mDescriptor.type(); 41 MOZ_CRASH("GFX: Bad descriptor"); 42 } 43 } 44 45 RenderExternalTextureHost::~RenderExternalTextureHost() { 46 MOZ_COUNT_DTOR_INHERITED(RenderExternalTextureHost, RenderTextureHost); 47 48 if (NS_WARN_IF(!IsReadyForDeletion())) { 49 gfxCriticalNote << "RenderExternalTextureHost sync failed"; 50 } 51 52 DeleteTextures(); 53 } 54 55 bool RenderExternalTextureHost::CreateSurfaces() { 56 if (!IsYUV()) { 57 mSurfaces[0] = gfx::Factory::CreateWrappingDataSourceSurface( 58 GetBuffer(), 59 layers::ImageDataSerializer::GetRGBStride( 60 mDescriptor.get_RGBDescriptor()), 61 mSize, mFormat); 62 } else { 63 const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); 64 const gfx::SurfaceFormat surfaceFormat = 65 SurfaceFormatForColorDepth(desc.colorDepth()); 66 auto cbcrSize = layers::ImageDataSerializer::GetCroppedCbCrSize(desc); 67 68 mSurfaces[0] = gfx::Factory::CreateWrappingDataSourceSurface( 69 layers::ImageDataSerializer::GetYChannel(GetBuffer(), desc), 70 desc.yStride(), desc.display().Size(), surfaceFormat); 71 mSurfaces[1] = gfx::Factory::CreateWrappingDataSourceSurface( 72 layers::ImageDataSerializer::GetCbChannel(GetBuffer(), desc), 73 desc.cbCrStride(), cbcrSize, surfaceFormat); 74 mSurfaces[2] = gfx::Factory::CreateWrappingDataSourceSurface( 75 layers::ImageDataSerializer::GetCrChannel(GetBuffer(), desc), 76 desc.cbCrStride(), cbcrSize, surfaceFormat); 77 } 78 79 for (size_t i = 0; i < PlaneCount(); ++i) { 80 if (NS_WARN_IF(!mSurfaces[i])) { 81 gfxCriticalNote << "Surface is null"; 82 return false; 83 } 84 } 85 86 return true; 87 } 88 89 void RenderExternalTextureHost::DeleteSurfaces() { 90 for (size_t i = 0; i < PlaneCount(); ++i) { 91 mSurfaces[i] = nullptr; 92 } 93 } 94 95 void RenderExternalTextureHost::DeleteTextures() { 96 for (size_t i = 0; i < PlaneCount(); ++i) { 97 mTextureSources[i] = nullptr; 98 mImages[i] = InvalidToWrExternalImage(); 99 } 100 } 101 102 bool RenderExternalTextureHost::InitializeIfNeeded() { 103 if (mInitialized) { 104 return true; 105 } 106 107 if (!GetBuffer()) { 108 // We hit some problems to get the shmem. 109 gfxCriticalNote << "GetBuffer Failed"; 110 return false; 111 } 112 113 if (!CreateSurfaces()) { 114 DeleteSurfaces(); 115 return false; 116 } 117 118 mInitialized = true; 119 return mInitialized; 120 } 121 122 bool RenderExternalTextureHost::IsReadyForDeletion() { 123 if (!mInitialized) { 124 return true; 125 } 126 127 auto& textureSource = mTextureSources[0]; 128 if (textureSource) { 129 return textureSource->Sync(false); 130 } 131 132 return true; 133 } 134 135 wr::WrExternalImage RenderExternalTextureHost::Lock(uint8_t aChannelIndex, 136 gl::GLContext* aGL) { 137 if (mGL.get() != aGL) { 138 mGL = aGL; 139 mGL->MakeCurrent(); 140 } 141 142 if (!mGL || !mGL->MakeCurrent()) { 143 return InvalidToWrExternalImage(); 144 } 145 146 if (!InitializeIfNeeded()) { 147 return InvalidToWrExternalImage(); 148 } 149 150 UpdateTextures(); 151 return mImages[aChannelIndex]; 152 } 153 154 void RenderExternalTextureHost::PrepareForUse() { mTextureUpdateNeeded = true; } 155 156 void RenderExternalTextureHost::Unlock() {} 157 158 void RenderExternalTextureHost::UpdateTexture(size_t aIndex) { 159 MOZ_ASSERT(mSurfaces[aIndex]); 160 161 auto& texture = mTextureSources[aIndex]; 162 163 if (texture) { 164 texture->Update(mSurfaces[aIndex]); 165 } else { 166 texture = new layers::DirectMapTextureSource(mGL, mSurfaces[aIndex]); 167 168 const GLuint handle = texture->GetTextureHandle(); 169 const gfx::IntSize size = texture->GetSize(); 170 mImages[aIndex] = NativeTextureToWrExternalImage( 171 handle, 0.0, 0.0, static_cast<float>(size.width), 172 static_cast<float>(size.height)); 173 } 174 175 MOZ_ASSERT(mGL->GetError() == LOCAL_GL_NO_ERROR); 176 } 177 178 void RenderExternalTextureHost::UpdateTextures() { 179 if (!mTextureUpdateNeeded) { 180 // Nothing to do here. 181 return; 182 } 183 184 for (size_t i = 0; i < PlaneCount(); ++i) { 185 UpdateTexture(i); 186 } 187 188 mTextureSources[0]->MaybeFenceTexture(); 189 mTextureUpdateNeeded = false; 190 } 191 192 size_t RenderExternalTextureHost::GetPlaneCount() const { return PlaneCount(); } 193 194 gfx::SurfaceFormat RenderExternalTextureHost::GetFormat() const { 195 return mFormat; 196 } 197 198 gfx::ColorDepth RenderExternalTextureHost::GetColorDepth() const { 199 switch (mDescriptor.type()) { 200 case layers::BufferDescriptor::TYCbCrDescriptor: 201 return mDescriptor.get_YCbCrDescriptor().colorDepth(); 202 default: 203 return gfx::ColorDepth::COLOR_8; 204 } 205 } 206 207 gfx::YUVRangedColorSpace RenderExternalTextureHost::GetYUVColorSpace() const { 208 switch (mDescriptor.type()) { 209 case layers::BufferDescriptor::TYCbCrDescriptor: 210 return gfx::GetYUVRangedColorSpace(mDescriptor.get_YCbCrDescriptor()); 211 default: 212 return gfx::YUVRangedColorSpace::Default; 213 } 214 } 215 216 bool RenderExternalTextureHost::MapPlane(RenderCompositor* aCompositor, 217 uint8_t aChannelIndex, 218 PlaneInfo& aPlaneInfo) { 219 if (!mBuffer) { 220 // We hit some problems to get the shmem. 221 gfxCriticalNote << "GetBuffer Failed"; 222 return false; 223 } 224 225 switch (mDescriptor.type()) { 226 case layers::BufferDescriptor::TYCbCrDescriptor: { 227 const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); 228 switch (aChannelIndex) { 229 case 0: 230 aPlaneInfo.mData = 231 layers::ImageDataSerializer::GetYChannel(mBuffer, desc); 232 aPlaneInfo.mStride = desc.yStride(); 233 aPlaneInfo.mSize = desc.display().Size(); 234 break; 235 case 1: 236 aPlaneInfo.mData = 237 layers::ImageDataSerializer::GetCbChannel(mBuffer, desc); 238 aPlaneInfo.mStride = desc.cbCrStride(); 239 aPlaneInfo.mSize = 240 layers::ImageDataSerializer::GetCroppedCbCrSize(desc); 241 break; 242 case 2: 243 aPlaneInfo.mData = 244 layers::ImageDataSerializer::GetCrChannel(mBuffer, desc); 245 aPlaneInfo.mStride = desc.cbCrStride(); 246 aPlaneInfo.mSize = 247 layers::ImageDataSerializer::GetCroppedCbCrSize(desc); 248 break; 249 } 250 break; 251 } 252 default: { 253 const layers::RGBDescriptor& desc = mDescriptor.get_RGBDescriptor(); 254 aPlaneInfo.mData = mBuffer; 255 aPlaneInfo.mStride = layers::ImageDataSerializer::GetRGBStride(desc); 256 aPlaneInfo.mSize = desc.size(); 257 break; 258 } 259 } 260 return true; 261 } 262 263 void RenderExternalTextureHost::UnmapPlanes() {} 264 265 } // namespace wr 266 } // namespace mozilla