RenderEGLImageTextureHost.cpp (6935B)
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 "RenderEGLImageTextureHost.h" 8 9 #include "mozilla/gfx/Logging.h" 10 #include "GLContextEGL.h" 11 #include "GLLibraryEGL.h" 12 #include "GLReadTexImageHelper.h" 13 #include "OGLShaderConfig.h" 14 15 namespace mozilla { 16 namespace wr { 17 18 RenderEGLImageTextureHost::RenderEGLImageTextureHost(EGLImage aImage, 19 EGLSync aSync, 20 gfx::IntSize aSize, 21 gfx::SurfaceFormat aFormat) 22 : mImage(aImage), 23 mSync(aSync), 24 mSize(aSize), 25 mFormat(aFormat), 26 mTextureTarget(LOCAL_GL_TEXTURE_2D), 27 mTextureHandle(0) { 28 MOZ_COUNT_CTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHost); 29 } 30 31 RenderEGLImageTextureHost::~RenderEGLImageTextureHost() { 32 MOZ_COUNT_DTOR_INHERITED(RenderEGLImageTextureHost, RenderTextureHost); 33 DeleteTextureHandle(); 34 } 35 36 wr::WrExternalImage RenderEGLImageTextureHost::Lock(uint8_t aChannelIndex, 37 gl::GLContext* aGL) { 38 MOZ_ASSERT(aChannelIndex == 0); 39 40 if (mGL.get() != aGL) { 41 if (mGL) { 42 // This should not happen. On android, SingletonGL is used. 43 MOZ_ASSERT_UNREACHABLE("Unexpected GL context"); 44 return InvalidToWrExternalImage(); 45 } 46 mGL = aGL; 47 } 48 49 if (!mImage || !mGL || !mGL->MakeCurrent()) { 50 return InvalidToWrExternalImage(); 51 } 52 53 if (!WaitSync() || !CreateTextureHandle()) { 54 return InvalidToWrExternalImage(); 55 } 56 57 return NativeTextureToWrExternalImage(mTextureHandle, 0.0, 0.0, 58 static_cast<float>(mSize.width), 59 static_cast<float>(mSize.height)); 60 } 61 62 void RenderEGLImageTextureHost::Unlock() {} 63 64 RefPtr<layers::TextureSource> RenderEGLImageTextureHost::CreateTextureSource( 65 layers::TextureSourceProvider* aProvider) { 66 gl::GLContext* gl = aProvider->GetGLContext(); 67 if (mGL.get() != gl) { 68 if (mGL) { 69 // This should not happen. On android, SingletonGL is used. 70 MOZ_ASSERT_UNREACHABLE("Unexpected GL context"); 71 return nullptr; 72 } 73 mGL = gl; 74 } 75 76 if (!WaitSync()) { 77 return nullptr; 78 } 79 80 return new layers::EGLImageTextureSource( 81 aProvider, mImage, mFormat, gl->GetPreferredEGLImageTextureTarget(), 82 LOCAL_GL_CLAMP_TO_EDGE, mSize); 83 } 84 85 gfx::SurfaceFormat RenderEGLImageTextureHost::GetFormat() const { 86 MOZ_ASSERT(mFormat == gfx::SurfaceFormat::R8G8B8A8 || 87 mFormat == gfx::SurfaceFormat::R8G8B8X8); 88 // SWGL does not support RGBA/RGBX so we must provide data in BGRA/BGRX 89 // format. ReadTexImage() called by MapPlane() will ensure that data gets 90 // converted correctly. 91 if (mFormat == gfx::SurfaceFormat::R8G8B8A8) { 92 return gfx::SurfaceFormat::B8G8R8A8; 93 } 94 95 if (mFormat == gfx::SurfaceFormat::R8G8B8X8) { 96 return gfx::SurfaceFormat::B8G8R8X8; 97 } 98 99 gfxCriticalNoteOnce << "Unexpected color format of RenderEGLImageTextureHost"; 100 101 return gfx::SurfaceFormat::UNKNOWN; 102 } 103 104 bool RenderEGLImageTextureHost::MapPlane(RenderCompositor* aCompositor, 105 uint8_t aChannelIndex, 106 PlaneInfo& aPlaneInfo) { 107 RefPtr<gfx::DataSourceSurface> readback = ReadTexImage(); 108 if (!readback) { 109 return false; 110 } 111 112 gfx::DataSourceSurface::MappedSurface map; 113 if (!readback->Map(gfx::DataSourceSurface::MapType::READ, &map)) { 114 return false; 115 } 116 117 mReadback = readback; 118 aPlaneInfo.mSize = mSize; 119 aPlaneInfo.mStride = map.mStride; 120 aPlaneInfo.mData = map.mData; 121 return true; 122 } 123 124 void RenderEGLImageTextureHost::UnmapPlanes() { 125 if (mReadback) { 126 mReadback->Unmap(); 127 mReadback = nullptr; 128 } 129 } 130 131 bool RenderEGLImageTextureHost::CreateTextureHandle() { 132 if (mTextureHandle) { 133 return true; 134 } 135 136 mTextureTarget = mGL->GetPreferredEGLImageTextureTarget(); 137 MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D || 138 mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL); 139 140 mGL->fGenTextures(1, &mTextureHandle); 141 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0, mTextureTarget, 142 mTextureHandle); 143 mGL->fEGLImageTargetTexture2D(mTextureTarget, mImage); 144 return true; 145 } 146 147 void RenderEGLImageTextureHost::DeleteTextureHandle() { 148 if (mTextureHandle) { 149 if (mGL && mGL->MakeCurrent()) { 150 // XXX recycle gl texture, since SharedSurface_EGLImage and 151 // RenderEGLImageTextureHost is not recycled. 152 mGL->fDeleteTextures(1, &mTextureHandle); 153 } 154 mTextureHandle = 0; 155 } 156 } 157 158 bool RenderEGLImageTextureHost::WaitSync() { 159 bool syncSucceeded = true; 160 if (mSync) { 161 const auto& gle = gl::GLContextEGL::Cast(mGL); 162 const auto& egl = gle->mEgl; 163 MOZ_ASSERT(egl->IsExtensionSupported(gl::EGLExtension::KHR_fence_sync)); 164 if (egl->IsExtensionSupported(gl::EGLExtension::KHR_wait_sync)) { 165 syncSucceeded = egl->fWaitSync(mSync, 0) == LOCAL_EGL_TRUE; 166 } else { 167 syncSucceeded = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER) == 168 LOCAL_EGL_CONDITION_SATISFIED; 169 } 170 // We do not need to delete sync here. It is deleted by 171 // SharedSurface_EGLImage. 172 mSync = 0; 173 } 174 175 MOZ_ASSERT( 176 syncSucceeded, 177 "(Client)WaitSync generated an error. Has mSync already been destroyed?"); 178 return syncSucceeded; 179 } 180 181 already_AddRefed<gfx::DataSourceSurface> 182 RenderEGLImageTextureHost::ReadTexImage() { 183 if (!mGL) { 184 mGL = RenderThread::Get()->SingletonGL(); 185 if (!mGL) { 186 return nullptr; 187 } 188 } 189 190 if (!WaitSync() || !CreateTextureHandle()) { 191 return nullptr; 192 } 193 194 // Allocate resulting image surface. 195 // Use GetFormat() rather than mFormat for the DataSourceSurface. eg BGRA 196 // rather than RGBA, as the latter is not supported by swgl. 197 // ReadTexImageHelper will take care of converting the data for us. 198 const gfx::SurfaceFormat surfFormat = GetFormat(); 199 int32_t stride = mSize.width * BytesPerPixel(surfFormat); 200 RefPtr<gfx::DataSourceSurface> surf = 201 gfx::Factory::CreateDataSourceSurfaceWithStride(mSize, surfFormat, 202 stride); 203 if (!surf) { 204 return nullptr; 205 } 206 207 layers::ShaderConfigOGL config = 208 layers::ShaderConfigFromTargetAndFormat(mTextureTarget, mFormat); 209 int shaderConfig = config.mFeatures; 210 211 bool ret = mGL->ReadTexImageHelper()->ReadTexImage( 212 surf, mTextureHandle, mTextureTarget, mSize, gfx::Matrix4x4(), 213 shaderConfig, /* aYInvert */ false); 214 if (!ret) { 215 return nullptr; 216 } 217 218 return surf.forget(); 219 } 220 221 } // namespace wr 222 } // namespace mozilla