tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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