tor-browser

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

CompositorOGL.cpp (60131B)


      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 "CompositorOGL.h"
      8 #include <stddef.h>             // for size_t
      9 #include <stdint.h>             // for uint32_t, uint8_t
     10 #include <stdlib.h>             // for free, malloc
     11 #include "GLContextProvider.h"  // for GLContextProvider
     12 #include "GLContext.h"          // for GLContext
     13 #include "GLUploadHelpers.h"
     14 #include "gfxCrashReporterUtils.h"  // for ScopedGfxFeatureReporter
     15 #include "gfxEnv.h"                 // for gfxEnv
     16 #include "gfxPlatform.h"            // for gfxPlatform
     17 #include "gfxRect.h"                // for gfxRect
     18 #include "gfxUtils.h"               // for gfxUtils, etc
     19 #include "mozilla/Preferences.h"    // for Preferences
     20 #include "mozilla/ProfilerLabels.h"
     21 #include "mozilla/StaticPrefs_gfx.h"
     22 #include "mozilla/StaticPrefs_layers.h"
     23 #include "mozilla/StaticPrefs_nglayout.h"
     24 #include "mozilla/gfx/BasePoint.h"  // for BasePoint
     25 #include "mozilla/gfx/Matrix.h"     // for Matrix4x4, Matrix
     26 #include "mozilla/gfx/Triangle.h"   // for Triangle
     27 #include "mozilla/gfx/gfxVars.h"    // for gfxVars
     28 #include "mozilla/layers/ImageDataSerializer.h"
     29 #include "mozilla/layers/NativeLayer.h"
     30 #include "mozilla/layers/CompositingRenderTargetOGL.h"
     31 #include "mozilla/layers/Effects.h"      // for EffectChain, TexturedEffect, etc
     32 #include "mozilla/layers/TextureHost.h"  // for TextureSource, etc
     33 #include "mozilla/layers/TextureHostOGL.h"  // for TextureSourceOGL, etc
     34 #include "mozilla/layers/PTextureParent.h"  // for OtherPid() on PTextureParent
     35 #include "mozilla/mozalloc.h"               // for operator delete, etc
     36 #include "nsAppRunner.h"
     37 #include "nsAString.h"
     38 #include "nsClassHashtable.h"
     39 #include "nsIConsoleService.h"      // for nsIConsoleService, etc
     40 #include "nsIWidget.h"              // for nsIWidget
     41 #include "nsLiteralString.h"        // for NS_LITERAL_STRING
     42 #include "nsMathUtils.h"            // for NS_roundf
     43 #include "nsRect.h"                 // for mozilla::gfx::IntRect
     44 #include "nsServiceManagerUtils.h"  // for do_GetService
     45 #include "nsString.h"               // for nsString, nsAutoCString, etc
     46 #include "OGLShaderProgram.h"       // for ShaderProgramOGL, etc
     47 #include "ScopedGLHelpers.h"
     48 #include "GLReadTexImageHelper.h"
     49 #include "HeapCopyOfStackArray.h"
     50 #include "GLBlitHelper.h"
     51 #include "mozilla/gfx/Swizzle.h"
     52 #ifdef MOZ_WIDGET_GTK
     53 #  include "mozilla/widget/GtkCompositorWidget.h"
     54 #endif
     55 #if MOZ_WIDGET_ANDROID
     56 #  include "GLContextEGL.h"
     57 #  include "GLLibraryEGL.h"
     58 #  include "mozilla/java/GeckoSurfaceTextureWrappers.h"
     59 #  include "mozilla/layers/AndroidHardwareBuffer.h"
     60 #endif
     61 
     62 namespace mozilla {
     63 
     64 using namespace gfx;
     65 
     66 namespace layers {
     67 
     68 using namespace mozilla::gl;
     69 
     70 static const GLuint kCoordinateAttributeIndex = 0;
     71 static const GLuint kTexCoordinateAttributeIndex = 1;
     72 
     73 class DummyTextureSourceOGL : public TextureSource, public TextureSourceOGL {
     74 public:
     75  const char* Name() const override { return "DummyTextureSourceOGL"; }
     76 
     77  TextureSourceOGL* AsSourceOGL() override { return this; }
     78 
     79  void BindTexture(GLenum activetex,
     80                   gfx::SamplingFilter aSamplingFilter) override {}
     81 
     82  bool IsValid() const override { return false; }
     83 
     84  gfx::IntSize GetSize() const override { return gfx::IntSize(); }
     85 
     86  gfx::SurfaceFormat GetFormat() const override {
     87    return gfx::SurfaceFormat::B8G8R8A8;
     88  }
     89 
     90  GLenum GetWrapMode() const override { return LOCAL_GL_CLAMP_TO_EDGE; }
     91 
     92 protected:
     93 };
     94 
     95 class AsyncReadbackBufferOGL final : public AsyncReadbackBuffer {
     96 public:
     97  AsyncReadbackBufferOGL(GLContext* aGL, const IntSize& aSize);
     98 
     99  bool MapAndCopyInto(DataSourceSurface* aSurface,
    100                      const IntSize& aReadSize) const override;
    101 
    102  void Bind() const {
    103    mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, mBufferHandle);
    104    mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 1);
    105  }
    106 
    107 protected:
    108  virtual ~AsyncReadbackBufferOGL();
    109 
    110 private:
    111  GLContext* mGL;
    112  GLuint mBufferHandle;
    113 };
    114 
    115 AsyncReadbackBufferOGL::AsyncReadbackBufferOGL(GLContext* aGL,
    116                                               const IntSize& aSize)
    117    : AsyncReadbackBuffer(aSize), mGL(aGL), mBufferHandle(0) {
    118  size_t bufferByteCount = mSize.width * mSize.height * 4;
    119  mGL->fGenBuffers(1, &mBufferHandle);
    120 
    121  ScopedPackState scopedPackState(mGL);
    122  Bind();
    123  mGL->fBufferData(LOCAL_GL_PIXEL_PACK_BUFFER, bufferByteCount, nullptr,
    124                   LOCAL_GL_STREAM_READ);
    125 }
    126 
    127 AsyncReadbackBufferOGL::~AsyncReadbackBufferOGL() {
    128  if (mGL && mGL->MakeCurrent()) {
    129    mGL->fDeleteBuffers(1, &mBufferHandle);
    130  }
    131 }
    132 
    133 bool AsyncReadbackBufferOGL::MapAndCopyInto(DataSourceSurface* aSurface,
    134                                            const IntSize& aReadSize) const {
    135  MOZ_RELEASE_ASSERT(aReadSize <= aSurface->GetSize());
    136 
    137  if (!mGL || !mGL->MakeCurrent()) {
    138    return false;
    139  }
    140 
    141  ScopedPackState scopedPackState(mGL);
    142  Bind();
    143 
    144  const uint8_t* srcData = nullptr;
    145  if (mGL->IsSupported(GLFeature::map_buffer_range)) {
    146    srcData = static_cast<uint8_t*>(mGL->fMapBufferRange(
    147        LOCAL_GL_PIXEL_PACK_BUFFER, 0, aReadSize.height * aReadSize.width * 4,
    148        LOCAL_GL_MAP_READ_BIT));
    149  } else {
    150    srcData = static_cast<uint8_t*>(
    151        mGL->fMapBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, LOCAL_GL_READ_ONLY));
    152  }
    153 
    154  if (!srcData) {
    155    return false;
    156  }
    157 
    158  int32_t srcStride = mSize.width * 4;  // Bind() sets an alignment of 1
    159  DataSourceSurface::ScopedMap map(aSurface, DataSourceSurface::WRITE);
    160  uint8_t* destData = map.GetData();
    161  int32_t destStride = map.GetStride();
    162  SurfaceFormat destFormat = aSurface->GetFormat();
    163  for (int32_t destRow = 0; destRow < aReadSize.height; destRow++) {
    164    // Turn srcData upside down during the copy.
    165    int32_t srcRow = aReadSize.height - 1 - destRow;
    166    const uint8_t* src = &srcData[srcRow * srcStride];
    167    uint8_t* dest = &destData[destRow * destStride];
    168    SwizzleData(src, srcStride, SurfaceFormat::R8G8B8A8, dest, destStride,
    169                destFormat, IntSize(aReadSize.width, 1));
    170  }
    171 
    172  mGL->fUnmapBuffer(LOCAL_GL_PIXEL_PACK_BUFFER);
    173 
    174  return true;
    175 }
    176 
    177 PerUnitTexturePoolOGL::PerUnitTexturePoolOGL(gl::GLContext* aGL)
    178    : mTextureTarget(0),  // zero is never a valid texture target
    179      mGL(aGL) {}
    180 
    181 PerUnitTexturePoolOGL::~PerUnitTexturePoolOGL() { DestroyTextures(); }
    182 
    183 CompositorOGL::CompositorOGL(widget::CompositorWidget* aWidget,
    184                             int aSurfaceWidth, int aSurfaceHeight,
    185                             bool aUseExternalSurfaceSize)
    186    : Compositor(aWidget),
    187      mWidgetSize(-1, -1),
    188      mSurfaceSize(aSurfaceWidth, aSurfaceHeight),
    189      mFBOTextureTarget(0),
    190      mWindowRenderTarget(nullptr),
    191      mQuadVBO(0),
    192      mTriangleVBO(0),
    193      mPreviousFrameDoneSync(nullptr),
    194      mThisFrameDoneSync(nullptr),
    195      mHasBGRA(0),
    196      mUseExternalSurfaceSize(aUseExternalSurfaceSize),
    197      mFrameInProgress(false),
    198      mDestroyed(false),
    199      mViewportSize(0, 0) {
    200  // If we render into native layers, our GLContext won't have a usable default
    201  // framebuffer.
    202  mCanRenderToDefaultFramebuffer = !aWidget->GetNativeLayerRoot();
    203  MOZ_COUNT_CTOR(CompositorOGL);
    204 }
    205 
    206 CompositorOGL::~CompositorOGL() { MOZ_COUNT_DTOR(CompositorOGL); }
    207 
    208 already_AddRefed<mozilla::gl::GLContext> CompositorOGL::CreateContext() {
    209  RefPtr<GLContext> context;
    210 
    211  // Used by mock widget to create an offscreen context
    212  nsIWidget* widget = mWidget->RealWidget();
    213  void* widgetOpenGLContext =
    214      widget ? widget->GetNativeData(NS_NATIVE_OPENGL_CONTEXT) : nullptr;
    215  if (widgetOpenGLContext) {
    216    GLContext* alreadyRefed = reinterpret_cast<GLContext*>(widgetOpenGLContext);
    217    return already_AddRefed<GLContext>(alreadyRefed);
    218  }
    219 
    220 #ifdef XP_WIN
    221  if (gfxEnv::MOZ_LAYERS_PREFER_EGL()) {
    222    printf_stderr("Trying GL layers...\n");
    223    context = gl::GLContextProviderEGL::CreateForCompositorWidget(
    224        mWidget, /* aHardwareWebRender */ false, /* aForceAccelerated */ false);
    225  }
    226 #endif
    227 
    228  // Allow to create offscreen GL context for main Layer Manager
    229  if (!context && gfxEnv::MOZ_LAYERS_PREFER_OFFSCREEN()) {
    230    nsCString discardFailureId;
    231    context = GLContextProvider::CreateHeadless(
    232        {CreateContextFlags::REQUIRE_COMPAT_PROFILE}, &discardFailureId);
    233    if (!context->CreateOffscreenDefaultFb(mSurfaceSize)) {
    234      context = nullptr;
    235    }
    236  }
    237 
    238  if (!context) {
    239    context = gl::GLContextProvider::CreateForCompositorWidget(
    240        mWidget,
    241        /* aHardwareWebRender */ false,
    242        gfxVars::RequiresAcceleratedGLContextForCompositorOGL());
    243  }
    244 
    245  if (!context) {
    246    NS_WARNING("Failed to create CompositorOGL context");
    247  }
    248 
    249  return context.forget();
    250 }
    251 
    252 void CompositorOGL::Destroy() {
    253  Compositor::Destroy();
    254 
    255  if (mTexturePool) {
    256    mTexturePool->Clear();
    257    mTexturePool = nullptr;
    258  }
    259 
    260  if (!mDestroyed) {
    261    mDestroyed = true;
    262    CleanupResources();
    263  }
    264 }
    265 
    266 void CompositorOGL::CleanupResources() {
    267  if (!mGLContext) return;
    268 
    269  if (mSurfacePoolHandle) {
    270    mSurfacePoolHandle->Pool()->DestroyGLResourcesForContext(mGLContext);
    271    mSurfacePoolHandle = nullptr;
    272  }
    273 
    274  RefPtr<GLContext> ctx = mGLContext->GetSharedContext();
    275  if (!ctx) {
    276    ctx = mGLContext;
    277  }
    278 
    279  if (!ctx->MakeCurrent()) {
    280    // Leak resources!
    281    mQuadVBO = 0;
    282    mTriangleVBO = 0;
    283    mPreviousFrameDoneSync = nullptr;
    284    mThisFrameDoneSync = nullptr;
    285    mProgramsHolder = nullptr;
    286    mGLContext = nullptr;
    287    mNativeLayersReferenceRT = nullptr;
    288    mFullWindowRenderTarget = nullptr;
    289    return;
    290  }
    291 
    292  mProgramsHolder = nullptr;
    293  mNativeLayersReferenceRT = nullptr;
    294  mFullWindowRenderTarget = nullptr;
    295 
    296 #ifdef MOZ_WIDGET_GTK
    297  // TextureSources might hold RefPtr<gl::GLContext>.
    298  // All of them needs to be released to destroy GLContext.
    299  // GLContextGLX has to be destroyed before related gtk window is destroyed.
    300  for (auto textureSource : mRegisteredTextureSources) {
    301    textureSource->DeallocateDeviceData();
    302  }
    303  mRegisteredTextureSources.clear();
    304 #endif
    305 
    306  ctx->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
    307 
    308  if (mQuadVBO) {
    309    ctx->fDeleteBuffers(1, &mQuadVBO);
    310    mQuadVBO = 0;
    311  }
    312 
    313  if (mTriangleVBO) {
    314    ctx->fDeleteBuffers(1, &mTriangleVBO);
    315    mTriangleVBO = 0;
    316  }
    317 
    318  mGLContext->MakeCurrent();
    319 
    320  if (mPreviousFrameDoneSync) {
    321    mGLContext->fDeleteSync(mPreviousFrameDoneSync);
    322    mPreviousFrameDoneSync = nullptr;
    323  }
    324 
    325  if (mThisFrameDoneSync) {
    326    mGLContext->fDeleteSync(mThisFrameDoneSync);
    327    mThisFrameDoneSync = nullptr;
    328  }
    329 
    330  if (mOwnsGLContext) {
    331    // On the main thread the Widget will be destroyed soon and calling
    332    // MakeCurrent after that could cause a crash (at least with GLX, see bug
    333    // 1059793), unless context is marked as destroyed. There may be some
    334    // textures still alive that will try to call MakeCurrent on the context so
    335    // let's make sure it is marked destroyed now.
    336    mGLContext->MarkDestroyed();
    337  }
    338 
    339  mGLContext = nullptr;
    340 }
    341 
    342 bool CompositorOGL::Initialize(GLContext* aGLContext,
    343                               RefPtr<ShaderProgramOGLsHolder> aProgramsHolder,
    344                               nsCString* const out_failureReason) {
    345  MOZ_ASSERT(!mDestroyed);
    346  MOZ_ASSERT(!mGLContext);
    347 
    348  mGLContext = aGLContext;
    349  mProgramsHolder = aProgramsHolder;
    350  mOwnsGLContext = false;
    351 
    352  return Initialize(out_failureReason);
    353 }
    354 
    355 bool CompositorOGL::Initialize(nsCString* const out_failureReason) {
    356  ScopedGfxFeatureReporter reporter("GL Layers");
    357 
    358  // Do not allow double initialization
    359  MOZ_ASSERT(mGLContext == nullptr || !mOwnsGLContext,
    360             "Don't reinitialize CompositorOGL");
    361 
    362  if (!mGLContext) {
    363    MOZ_ASSERT(mOwnsGLContext);
    364    mGLContext = CreateContext();
    365  }
    366 
    367 #ifdef MOZ_WIDGET_ANDROID
    368  if (!mGLContext) {
    369    *out_failureReason = "FEATURE_FAILURE_OPENGL_NO_ANDROID_CONTEXT";
    370    MOZ_CRASH("We need a context on Android");
    371  }
    372 #endif
    373 
    374  if (!mGLContext) {
    375    *out_failureReason = "FEATURE_FAILURE_OPENGL_CREATE_CONTEXT";
    376    return false;
    377  }
    378 
    379  if (!mProgramsHolder) {
    380    mProgramsHolder = new ShaderProgramOGLsHolder(mGLContext);
    381  }
    382 
    383  MakeCurrent();
    384 
    385  mHasBGRA = mGLContext->IsExtensionSupported(
    386                 gl::GLContext::EXT_texture_format_BGRA8888) ||
    387             mGLContext->IsExtensionSupported(gl::GLContext::EXT_bgra);
    388 
    389  mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
    390                                 LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
    391  mGLContext->fEnable(LOCAL_GL_BLEND);
    392 
    393  // initialise a common shader to check that we can actually compile a shader
    394  RefPtr<DummyTextureSourceOGL> source = new DummyTextureSourceOGL;
    395  RefPtr<EffectRGB> effect =
    396      new EffectRGB(source, /* aPremultiplied */ true, SamplingFilter::GOOD);
    397  ShaderConfigOGL config = GetShaderConfigFor(effect);
    398  if (!GetShaderProgramFor(config)) {
    399    *out_failureReason = "FEATURE_FAILURE_OPENGL_COMPILE_SHADER";
    400    return false;
    401  }
    402 
    403  if (mGLContext->WorkAroundDriverBugs()) {
    404    /**
    405     * We'll test the ability here to bind NPOT textures to a framebuffer, if
    406     * this fails we'll try ARB_texture_rectangle.
    407     */
    408 
    409    GLenum textureTargets[] = {LOCAL_GL_TEXTURE_2D, LOCAL_GL_NONE};
    410 
    411    if (!mGLContext->IsGLES()) {
    412      // No TEXTURE_RECTANGLE_ARB available on ES2
    413      textureTargets[1] = LOCAL_GL_TEXTURE_RECTANGLE_ARB;
    414    }
    415 
    416    mFBOTextureTarget = LOCAL_GL_NONE;
    417 
    418    GLuint testFBO = 0;
    419    mGLContext->fGenFramebuffers(1, &testFBO);
    420    GLuint testTexture = 0;
    421 
    422    for (uint32_t i = 0; i < std::size(textureTargets); i++) {
    423      GLenum target = textureTargets[i];
    424      if (!target) continue;
    425 
    426      mGLContext->fGenTextures(1, &testTexture);
    427      mGLContext->fBindTexture(target, testTexture);
    428      mGLContext->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER,
    429                                 LOCAL_GL_NEAREST);
    430      mGLContext->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER,
    431                                 LOCAL_GL_NEAREST);
    432      mGLContext->fTexImage2D(
    433          target, 0, LOCAL_GL_RGBA, 5, 3, /* sufficiently NPOT */
    434          0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
    435 
    436      // unbind this texture, in preparation for binding it to the FBO
    437      mGLContext->fBindTexture(target, 0);
    438 
    439      mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, testFBO);
    440      mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    441                                        LOCAL_GL_COLOR_ATTACHMENT0, target,
    442                                        testTexture, 0);
    443 
    444      if (mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) ==
    445          LOCAL_GL_FRAMEBUFFER_COMPLETE) {
    446        mFBOTextureTarget = target;
    447        mGLContext->fDeleteTextures(1, &testTexture);
    448        break;
    449      }
    450 
    451      mGLContext->fDeleteTextures(1, &testTexture);
    452    }
    453 
    454    if (testFBO) {
    455      mGLContext->fDeleteFramebuffers(1, &testFBO);
    456    }
    457 
    458    if (mFBOTextureTarget == LOCAL_GL_NONE) {
    459      /* Unable to find a texture target that works with FBOs and NPOT textures
    460       */
    461      *out_failureReason = "FEATURE_FAILURE_OPENGL_NO_TEXTURE_TARGET";
    462      return false;
    463    }
    464  } else {
    465    // not trying to work around driver bugs, so TEXTURE_2D should just work
    466    mFBOTextureTarget = LOCAL_GL_TEXTURE_2D;
    467  }
    468 
    469  // back to default framebuffer, to avoid confusion
    470  mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
    471 
    472  if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
    473    /* If we're using TEXTURE_RECTANGLE, then we must have the ARB
    474     * extension -- the EXT variant does not provide support for
    475     * texture rectangle access inside GLSL (sampler2DRect,
    476     * texture2DRect).
    477     */
    478    if (!mGLContext->IsExtensionSupported(
    479            gl::GLContext::ARB_texture_rectangle)) {
    480      *out_failureReason = "FEATURE_FAILURE_OPENGL_ARB_EXT";
    481      return false;
    482    }
    483  }
    484 
    485  // Create a VBO for triangle vertices.
    486  mGLContext->fGenBuffers(1, &mTriangleVBO);
    487 
    488  /* Create a simple quad VBO */
    489  mGLContext->fGenBuffers(1, &mQuadVBO);
    490 
    491  // 4 quads, with the number of the quad (vertexID) encoded in w.
    492  GLfloat vertices[] = {
    493      0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    494      1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
    495 
    496      0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
    497      1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
    498 
    499      0.0f, 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 2.0f,
    500      1.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 2.0f,
    501 
    502      0.0f, 0.0f, 0.0f, 3.0f, 1.0f, 0.0f, 0.0f, 3.0f, 0.0f, 1.0f, 0.0f, 3.0f,
    503      1.0f, 0.0f, 0.0f, 3.0f, 0.0f, 1.0f, 0.0f, 3.0f, 1.0f, 1.0f, 0.0f, 3.0f,
    504  };
    505  HeapCopyOfStackArray<GLfloat> verticesOnHeap(vertices);
    506 
    507  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
    508  mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, verticesOnHeap.ByteLength(),
    509                          verticesOnHeap.Data(), LOCAL_GL_STATIC_DRAW);
    510  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
    511 
    512  nsCOMPtr<nsIConsoleService> console(
    513      do_GetService(NS_CONSOLESERVICE_CONTRACTID));
    514 
    515  if (console) {
    516    nsString msg;
    517    msg += nsLiteralString(
    518        u"OpenGL compositor Initialized Succesfully.\nVersion: ");
    519    msg += NS_ConvertUTF8toUTF16(nsDependentCString(
    520        (const char*)mGLContext->fGetString(LOCAL_GL_VERSION)));
    521    msg += u"\nVendor: "_ns;
    522    msg += NS_ConvertUTF8toUTF16(nsDependentCString(
    523        (const char*)mGLContext->fGetString(LOCAL_GL_VENDOR)));
    524    msg += u"\nRenderer: "_ns;
    525    msg += NS_ConvertUTF8toUTF16(nsDependentCString(
    526        (const char*)mGLContext->fGetString(LOCAL_GL_RENDERER)));
    527    msg += u"\nFBO Texture Target: "_ns;
    528    if (mFBOTextureTarget == LOCAL_GL_TEXTURE_2D)
    529      msg += u"TEXTURE_2D"_ns;
    530    else
    531      msg += u"TEXTURE_RECTANGLE"_ns;
    532    console->LogStringMessage(msg.get());
    533  }
    534 
    535  reporter.SetSuccessful();
    536 
    537  return true;
    538 }
    539 
    540 /*
    541 * Returns a size that is equal to, or larger than and closest to,
    542 * aSize where both width and height are powers of two.
    543 * If the OpenGL setup is capable of using non-POT textures,
    544 * then it will just return aSize.
    545 */
    546 static IntSize CalculatePOTSize(const IntSize& aSize, GLContext* gl) {
    547  if (CanUploadNonPowerOfTwo(gl)) return aSize;
    548 
    549  return IntSize(RoundUpPow2(aSize.width), RoundUpPow2(aSize.height));
    550 }
    551 
    552 gfx::Rect CompositorOGL::GetTextureCoordinates(gfx::Rect textureRect,
    553                                               TextureSource* aTexture) {
    554  // If the OpenGL setup does not support non-power-of-two textures then the
    555  // texture's width and height will have been increased to the next
    556  // power-of-two (unless already a power of two). In that case we must scale
    557  // the texture coordinates to account for that.
    558  if (!CanUploadNonPowerOfTwo(mGLContext)) {
    559    const IntSize& textureSize = aTexture->GetSize();
    560    const IntSize potSize = CalculatePOTSize(textureSize, mGLContext);
    561    if (potSize != textureSize) {
    562      const float xScale = (float)textureSize.width / (float)potSize.width;
    563      const float yScale = (float)textureSize.height / (float)potSize.height;
    564      textureRect.Scale(xScale, yScale);
    565    }
    566  }
    567 
    568  return textureRect;
    569 }
    570 
    571 void CompositorOGL::PrepareViewport(CompositingRenderTargetOGL* aRenderTarget) {
    572  MOZ_ASSERT(aRenderTarget);
    573  // Logical surface size.
    574  const gfx::IntSize& size = aRenderTarget->GetSize();
    575  // Physical surface size.
    576  const gfx::IntSize& phySize = aRenderTarget->GetPhysicalSize();
    577 
    578  // Set the viewport correctly.
    579  mGLContext->fViewport(mSurfaceOrigin.x, mSurfaceOrigin.y, phySize.width,
    580                        phySize.height);
    581 
    582  mViewportSize = size;
    583 
    584  if (!aRenderTarget->HasComplexProjection()) {
    585    // We flip the view matrix around so that everything is right-side up; we're
    586    // drawing directly into the window's back buffer, so this keeps things
    587    // looking correct.
    588    // XXX: We keep track of whether the window size changed, so we could skip
    589    // this update if it hadn't changed since the last call.
    590 
    591    // Matrix to transform (0, 0, aWidth, aHeight) to viewport space (-1.0, 1.0,
    592    // 2, 2) and flip the contents.
    593    Matrix viewMatrix;
    594    viewMatrix.PreTranslate(-1.0, 1.0);
    595    viewMatrix.PreScale(2.0f / float(size.width), 2.0f / float(size.height));
    596    viewMatrix.PreScale(1.0f, -1.0f);
    597 
    598    MOZ_ASSERT(mCurrentRenderTarget, "No destination");
    599 
    600    Matrix4x4 matrix3d = Matrix4x4::From2D(viewMatrix);
    601    matrix3d._33 = 0.0f;
    602    mProjMatrix = matrix3d;
    603    mGLContext->fDepthRange(0.0f, 1.0f);
    604  } else {
    605    bool depthEnable;
    606    float zNear, zFar;
    607    aRenderTarget->GetProjection(mProjMatrix, depthEnable, zNear, zFar);
    608    mGLContext->fDepthRange(zNear, zFar);
    609  }
    610 }
    611 
    612 already_AddRefed<CompositingRenderTarget> CompositorOGL::CreateRenderTarget(
    613    const IntRect& aRect, SurfaceInitMode aInit) {
    614  MOZ_ASSERT(!aRect.IsZeroArea(),
    615             "Trying to create a render target of invalid size");
    616 
    617  if (aRect.IsZeroArea()) {
    618    return nullptr;
    619  }
    620 
    621  if (!gl()) {
    622    // CompositingRenderTargetOGL does not work without a gl context.
    623    return nullptr;
    624  }
    625 
    626  GLuint tex = 0;
    627  GLuint fbo = 0;
    628  IntRect rect = aRect;
    629  IntSize fboSize;
    630  CreateFBOWithTexture(rect, false, 0, &fbo, &tex, &fboSize);
    631  return CompositingRenderTargetOGL::CreateForNewFBOAndTakeOwnership(
    632      this, tex, fbo, aRect, aRect.TopLeft(), aRect.Size(), mFBOTextureTarget,
    633      aInit);
    634 }
    635 
    636 void CompositorOGL::SetRenderTarget(CompositingRenderTarget* aSurface) {
    637  MOZ_ASSERT(aSurface);
    638  CompositingRenderTargetOGL* surface =
    639      static_cast<CompositingRenderTargetOGL*>(aSurface);
    640  if (mCurrentRenderTarget != surface) {
    641    mCurrentRenderTarget = surface;
    642    surface->BindRenderTarget();
    643  }
    644 
    645  PrepareViewport(mCurrentRenderTarget);
    646 }
    647 
    648 already_AddRefed<CompositingRenderTarget>
    649 CompositorOGL::GetCurrentRenderTarget() const {
    650  return do_AddRef(mCurrentRenderTarget);
    651 }
    652 
    653 already_AddRefed<CompositingRenderTarget> CompositorOGL::GetWindowRenderTarget()
    654    const {
    655  return do_AddRef(mWindowRenderTarget);
    656 }
    657 
    658 already_AddRefed<AsyncReadbackBuffer> CompositorOGL::CreateAsyncReadbackBuffer(
    659    const IntSize& aSize) {
    660  return MakeAndAddRef<AsyncReadbackBufferOGL>(mGLContext, aSize);
    661 }
    662 
    663 bool CompositorOGL::ReadbackRenderTarget(CompositingRenderTarget* aSource,
    664                                         AsyncReadbackBuffer* aDest) {
    665  IntSize size = aSource->GetSize();
    666  MOZ_RELEASE_ASSERT(aDest->GetSize() == size);
    667 
    668  RefPtr<CompositingRenderTarget> previousTarget = GetCurrentRenderTarget();
    669  if (previousTarget != aSource) {
    670    SetRenderTarget(aSource);
    671  }
    672 
    673  ScopedPackState scopedPackState(mGLContext);
    674  static_cast<AsyncReadbackBufferOGL*>(aDest)->Bind();
    675 
    676  mGLContext->fReadPixels(0, 0, size.width, size.height, LOCAL_GL_RGBA,
    677                          LOCAL_GL_UNSIGNED_BYTE, 0);
    678 
    679  if (previousTarget != aSource) {
    680    SetRenderTarget(previousTarget);
    681  }
    682  return true;
    683 }
    684 
    685 bool CompositorOGL::BlitRenderTarget(CompositingRenderTarget* aSource,
    686                                     const gfx::IntSize& aSourceSize,
    687                                     const gfx::IntSize& aDestSize) {
    688  if (!mGLContext->IsSupported(GLFeature::framebuffer_blit)) {
    689    return false;
    690  }
    691  CompositingRenderTargetOGL* source =
    692      static_cast<CompositingRenderTargetOGL*>(aSource);
    693  GLuint srcFBO = source->GetFBO();
    694  GLuint destFBO = mCurrentRenderTarget->GetFBO();
    695  mGLContext->BlitHelper()->BlitFramebufferToFramebuffer(
    696      srcFBO, destFBO, IntRect(IntPoint(), aSourceSize),
    697      IntRect(IntPoint(), aDestSize), LOCAL_GL_LINEAR);
    698  return true;
    699 }
    700 
    701 static GLenum GetFrameBufferInternalFormat(
    702    GLContext* gl, GLuint aFrameBuffer,
    703    mozilla::widget::CompositorWidget* aWidget) {
    704  if (aFrameBuffer == 0) {  // default framebuffer
    705    return aWidget->GetGLFrameBufferFormat();
    706  }
    707  return LOCAL_GL_RGBA;
    708 }
    709 
    710 Maybe<IntRect> CompositorOGL::BeginFrameForWindow(
    711    const nsIntRegion& aInvalidRegion, const Maybe<IntRect>& aClipRect,
    712    const IntRect& aRenderBounds, const nsIntRegion& aOpaqueRegion) {
    713  MOZ_RELEASE_ASSERT(!mTarget, "mTarget not cleared properly");
    714  return BeginFrame(aInvalidRegion, aClipRect, aRenderBounds, aOpaqueRegion);
    715 }
    716 
    717 Maybe<IntRect> CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
    718                                         const Maybe<IntRect>& aClipRect,
    719                                         const IntRect& aRenderBounds,
    720                                         const nsIntRegion& aOpaqueRegion) {
    721  AUTO_PROFILER_LABEL("CompositorOGL::BeginFrame", GRAPHICS);
    722 
    723  MOZ_ASSERT(!mFrameInProgress,
    724             "frame still in progress (should have called EndFrame");
    725 
    726  IntRect rect;
    727  if (mUseExternalSurfaceSize) {
    728    rect = IntRect(IntPoint(), mSurfaceSize);
    729  } else {
    730    rect = aRenderBounds;
    731  }
    732 
    733  // We can't draw anything to something with no area
    734  // so just return
    735  if (rect.IsZeroArea()) {
    736    return Nothing();
    737  }
    738 
    739  // If the widget size changed, we have to force a MakeCurrent
    740  // to make sure that GL sees the updated widget size.
    741  if (mWidgetSize.ToUnknownSize() != rect.Size()) {
    742    MakeCurrent(ForceMakeCurrent);
    743 
    744    mWidgetSize = LayoutDeviceIntSize::FromUnknownSize(rect.Size());
    745 #ifdef MOZ_WAYLAND
    746    if (mWidget && mWidget->AsGTK()) {
    747      // Set correct window size to avoid rendering artifacts.
    748      mWidget->AsGTK()->SetEGLNativeWindowSize(mWidgetSize);
    749    }
    750 #endif
    751  } else {
    752    MakeCurrent();
    753  }
    754 
    755 #ifdef MOZ_WIDGET_ANDROID
    756  java::GeckoSurfaceTexture::DestroyUnused((int64_t)mGLContext.get());
    757  mGLContext->MakeCurrent();  // DestroyUnused can change the current context!
    758 #endif
    759 
    760  // Default blend function implements "OVER"
    761  mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
    762                                 LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
    763  mGLContext->fEnable(LOCAL_GL_BLEND);
    764 
    765  RefPtr<CompositingRenderTarget> rt;
    766  if (mCanRenderToDefaultFramebuffer) {
    767    rt = CompositingRenderTargetOGL::CreateForWindow(this, rect.Size());
    768  } else if (mTarget) {
    769    rt = CreateRenderTarget(rect, INIT_MODE_CLEAR);
    770  } else {
    771    MOZ_CRASH("Unexpected call");
    772  }
    773 
    774  if (!rt) {
    775    return Nothing();
    776  }
    777 
    778  // We're about to actually draw a frame.
    779  mFrameInProgress = true;
    780 
    781  SetRenderTarget(rt);
    782  mWindowRenderTarget = mCurrentRenderTarget;
    783 
    784  for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
    785    const IntRect& r = iter.Get();
    786    mCurrentFrameInvalidRegion.OrWith(
    787        IntRect(r.X(), FlipY(r.YMost()), r.Width(), r.Height()));
    788  }
    789  // Check to see if there is any transparent dirty region that would require
    790  // clearing. If not, just invalidate the framebuffer if supported.
    791  // TODO: Currently we initialize the clear region to the widget bounds as
    792  // SwapBuffers will update the entire framebuffer. On platforms that support
    793  // damage regions, we could initialize this to mCurrentFrameInvalidRegion.
    794  IntRegion regionToClear(rect);
    795  regionToClear.SubOut(aOpaqueRegion);
    796  GLbitfield clearBits = LOCAL_GL_DEPTH_BUFFER_BIT;
    797  if (regionToClear.IsEmpty() &&
    798      mGLContext->IsSupported(GLFeature::invalidate_framebuffer)) {
    799    GLenum attachments[] = {LOCAL_GL_COLOR};
    800    mGLContext->fInvalidateFramebuffer(LOCAL_GL_FRAMEBUFFER,
    801                                       std::size(attachments), attachments);
    802  } else {
    803    clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
    804  }
    805 
    806 #if defined(MOZ_WIDGET_ANDROID)
    807  if ((mSurfaceOrigin.x > 0) || (mSurfaceOrigin.y > 0)) {
    808    mGLContext->fClearColor(
    809        StaticPrefs::gfx_compositor_override_clear_color_r(),
    810        StaticPrefs::gfx_compositor_override_clear_color_g(),
    811        StaticPrefs::gfx_compositor_override_clear_color_b(),
    812        StaticPrefs::gfx_compositor_override_clear_color_a());
    813  } else {
    814    mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b,
    815                            mClearColor.a);
    816  }
    817 #else
    818  mGLContext->fClearColor(mClearColor.r, mClearColor.g, mClearColor.b,
    819                          mClearColor.a);
    820 #endif  // defined(MOZ_WIDGET_ANDROID)
    821  mGLContext->fClear(clearBits);
    822 
    823  return Some(rect);
    824 }
    825 
    826 void CompositorOGL::CreateFBOWithTexture(const gfx::IntRect& aRect,
    827                                         bool aCopyFromSource,
    828                                         GLuint aSourceFrameBuffer,
    829                                         GLuint* aFBO, GLuint* aTexture,
    830                                         gfx::IntSize* aAllocSize) {
    831  *aTexture =
    832      CreateTexture(aRect, aCopyFromSource, aSourceFrameBuffer, aAllocSize);
    833  mGLContext->fGenFramebuffers(1, aFBO);
    834 }
    835 
    836 GLuint CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
    837                                    GLuint aSourceFrameBuffer,
    838                                    IntSize* aAllocSize) {
    839  // we're about to create a framebuffer backed by textures to use as an
    840  // intermediate surface. What to do if its size (as given by aRect) would
    841  // exceed the maximum texture size supported by the GL? The present code
    842  // chooses the compromise of just clamping the framebuffer's size to the max
    843  // supported size. This gives us a lower resolution rendering of the
    844  // intermediate surface (children layers). See bug 827170 for a discussion.
    845  IntRect clampedRect = aRect;
    846  int32_t maxTexSize = GetMaxTextureSize();
    847  clampedRect.SetWidth(std::min(clampedRect.Width(), maxTexSize));
    848  clampedRect.SetHeight(std::min(clampedRect.Height(), maxTexSize));
    849 
    850  auto clampedRectWidth = clampedRect.Width();
    851  auto clampedRectHeight = clampedRect.Height();
    852 
    853  GLuint tex;
    854 
    855  mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
    856  mGLContext->fGenTextures(1, &tex);
    857  mGLContext->fBindTexture(mFBOTextureTarget, tex);
    858 
    859  if (aCopyFromSource) {
    860    GLuint curFBO = mCurrentRenderTarget->GetFBO();
    861    if (curFBO != aSourceFrameBuffer) {
    862      mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aSourceFrameBuffer);
    863    }
    864 
    865    // We're going to create an RGBA temporary fbo.  But to
    866    // CopyTexImage() from the current framebuffer, the framebuffer's
    867    // format has to be compatible with the new texture's.  So we
    868    // check the format of the framebuffer here and take a slow path
    869    // if it's incompatible.
    870    GLenum format =
    871        GetFrameBufferInternalFormat(gl(), aSourceFrameBuffer, mWidget);
    872 
    873    bool isFormatCompatibleWithRGBA =
    874        gl()->IsGLES() ? (format == LOCAL_GL_RGBA) : true;
    875 
    876    if (isFormatCompatibleWithRGBA) {
    877      mGLContext->fCopyTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
    878                                  clampedRect.X(), FlipY(clampedRect.YMost()),
    879                                  clampedRectWidth, clampedRectHeight, 0);
    880    } else {
    881      // Curses, incompatible formats.  Take a slow path.
    882 
    883      // RGBA
    884      size_t bufferSize = clampedRectWidth * clampedRectHeight * 4;
    885      auto buf = MakeUnique<uint8_t[]>(bufferSize);
    886 
    887      mGLContext->fReadPixels(clampedRect.X(), clampedRect.Y(),
    888                              clampedRectWidth, clampedRectHeight,
    889                              LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
    890      mGLContext->fTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
    891                              clampedRectWidth, clampedRectHeight, 0,
    892                              LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
    893    }
    894 
    895    GLenum error = mGLContext->fGetError();
    896    if (error != LOCAL_GL_NO_ERROR) {
    897      nsAutoCString msg;
    898      msg.AppendPrintf(
    899          "Texture initialization failed! -- error 0x%x, Source %d, Source "
    900          "format %d,  RGBA Compat %d",
    901          error, aSourceFrameBuffer, format, isFormatCompatibleWithRGBA);
    902      NS_ERROR(msg.get());
    903    }
    904  } else {
    905    mGLContext->fTexImage2D(mFBOTextureTarget, 0, LOCAL_GL_RGBA,
    906                            clampedRectWidth, clampedRectHeight, 0,
    907                            LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
    908  }
    909  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MIN_FILTER,
    910                             LOCAL_GL_LINEAR);
    911  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_MAG_FILTER,
    912                             LOCAL_GL_LINEAR);
    913  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_S,
    914                             LOCAL_GL_CLAMP_TO_EDGE);
    915  mGLContext->fTexParameteri(mFBOTextureTarget, LOCAL_GL_TEXTURE_WRAP_T,
    916                             LOCAL_GL_CLAMP_TO_EDGE);
    917  mGLContext->fBindTexture(mFBOTextureTarget, 0);
    918 
    919  if (aAllocSize) {
    920    aAllocSize->width = clampedRectWidth;
    921    aAllocSize->height = clampedRectHeight;
    922  }
    923 
    924  return tex;
    925 }
    926 
    927 ShaderConfigOGL CompositorOGL::GetShaderConfigFor(Effect* aEffect,
    928                                                  bool aDEAAEnabled,
    929                                                  bool aRoundedClip) const {
    930  ShaderConfigOGL config;
    931 
    932  switch (aEffect->mType) {
    933    case EffectTypes::YCBCR: {
    934      config.SetYCbCr(true);
    935      EffectYCbCr* effectYCbCr = static_cast<EffectYCbCr*>(aEffect);
    936      config.SetColorMultiplier(
    937          RescalingFactorForColorDepth(effectYCbCr->mColorDepth));
    938      config.SetTextureTarget(
    939          effectYCbCr->mTexture->AsSourceOGL()->GetTextureTarget());
    940      break;
    941    }
    942    case EffectTypes::NV12:
    943      config.SetNV12(true);
    944      if (gl()->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle)) {
    945        config.SetTextureTarget(LOCAL_GL_TEXTURE_RECTANGLE_ARB);
    946      } else {
    947        config.SetTextureTarget(LOCAL_GL_TEXTURE_2D);
    948      }
    949      break;
    950    default: {
    951      MOZ_ASSERT(aEffect->mType == EffectTypes::RGB);
    952      TexturedEffect* texturedEffect = static_cast<TexturedEffect*>(aEffect);
    953      TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
    954      MOZ_ASSERT_IF(
    955          source->GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL,
    956          source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
    957              source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||
    958              source->GetFormat() == gfx::SurfaceFormat::B8G8R8A8 ||
    959              source->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 ||
    960              source->GetFormat() == gfx::SurfaceFormat::R5G6B5_UINT16);
    961      MOZ_ASSERT_IF(
    962          source->GetTextureTarget() == LOCAL_GL_TEXTURE_RECTANGLE_ARB,
    963          source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
    964              source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||
    965              source->GetFormat() == gfx::SurfaceFormat::R5G6B5_UINT16 ||
    966              source->GetFormat() == gfx::SurfaceFormat::YUY2);
    967      config = ShaderConfigFromTargetAndFormat(source->GetTextureTarget(),
    968                                               source->GetFormat());
    969      if (!texturedEffect->mPremultiplied) {
    970        config.SetNoPremultipliedAlpha();
    971      }
    972      break;
    973    }
    974  }
    975  config.SetDEAA(aDEAAEnabled);
    976  config.SetRoundedClip(aRoundedClip);
    977  return config;
    978 }
    979 
    980 ShaderProgramOGL* CompositorOGL::GetShaderProgramFor(
    981    const ShaderConfigOGL& aConfig) {
    982  ShaderProgramOGL* shader = mProgramsHolder->GetShaderProgramFor(aConfig);
    983  return shader;
    984 }
    985 
    986 void CompositorOGL::ResetProgram() { mProgramsHolder->ResetCurrentProgram(); }
    987 
    988 static bool SetBlendMode(GLContext* aGL, gfx::CompositionOp aBlendMode,
    989                         bool aIsPremultiplied = true) {
    990  if (BlendOpIsMixBlendMode(aBlendMode)) {
    991    // Mix-blend modes require an extra step (or more) that cannot be expressed
    992    // in the fixed-function blending capabilities of opengl. We handle them
    993    // separately in shaders, and the shaders assume we will use our default
    994    // blend function for compositing (premultiplied OP_OVER).
    995    return false;
    996  }
    997  if (aBlendMode == gfx::CompositionOp::OP_OVER && aIsPremultiplied) {
    998    return false;
    999  }
   1000 
   1001  GLenum srcBlend;
   1002  GLenum dstBlend;
   1003  GLenum srcAlphaBlend = LOCAL_GL_ONE;
   1004  GLenum dstAlphaBlend = LOCAL_GL_ONE_MINUS_SRC_ALPHA;
   1005 
   1006  switch (aBlendMode) {
   1007    case gfx::CompositionOp::OP_OVER:
   1008      MOZ_ASSERT(!aIsPremultiplied);
   1009      srcBlend = LOCAL_GL_SRC_ALPHA;
   1010      dstBlend = LOCAL_GL_ONE_MINUS_SRC_ALPHA;
   1011      break;
   1012    case gfx::CompositionOp::OP_SOURCE:
   1013      srcBlend = aIsPremultiplied ? LOCAL_GL_ONE : LOCAL_GL_SRC_ALPHA;
   1014      dstBlend = LOCAL_GL_ZERO;
   1015      srcAlphaBlend = LOCAL_GL_ONE;
   1016      dstAlphaBlend = LOCAL_GL_ZERO;
   1017      break;
   1018    default:
   1019      MOZ_ASSERT_UNREACHABLE("Unsupported blend mode!");
   1020      return false;
   1021  }
   1022 
   1023  aGL->fBlendFuncSeparate(srcBlend, dstBlend, srcAlphaBlend, dstAlphaBlend);
   1024  return true;
   1025 }
   1026 
   1027 gfx::Point3D CompositorOGL::GetLineCoefficients(const gfx::Point& aPoint1,
   1028                                                const gfx::Point& aPoint2) {
   1029  // Return standard coefficients for a line between aPoint1 and aPoint2
   1030  // for standard line equation:
   1031  //
   1032  // Ax + By + C = 0
   1033  //
   1034  // A = (p1.y – p2.y)
   1035  // B = (p2.x – p1.x)
   1036  // C = (p1.x * p2.y) – (p2.x * p1.y)
   1037 
   1038  gfx::Point3D coeffecients;
   1039  coeffecients.x = aPoint1.y - aPoint2.y;
   1040  coeffecients.y = aPoint2.x - aPoint1.x;
   1041  coeffecients.z =
   1042      aPoint1.x.value * aPoint2.y.value - aPoint2.x.value * aPoint1.y.value;
   1043 
   1044  coeffecients *= 1.0f / sqrtf(coeffecients.x * coeffecients.x +
   1045                               coeffecients.y * coeffecients.y);
   1046 
   1047  // Offset outwards by 0.5 pixel as the edge is considered to be 1 pixel
   1048  // wide and included within the interior of the polygon
   1049  coeffecients.z += 0.5f;
   1050 
   1051  return coeffecients;
   1052 }
   1053 
   1054 void CompositorOGL::DrawQuad(const Rect& aRect, const IntRect& aClipRect,
   1055                             const EffectChain& aEffectChain, Float aOpacity,
   1056                             const gfx::Matrix4x4& aTransform,
   1057                             const gfx::Rect& aVisibleRect) {
   1058  AUTO_PROFILER_LABEL("CompositorOGL::DrawQuad", GRAPHICS);
   1059 
   1060  DrawGeometry(aRect, aRect, aClipRect, aEffectChain, aOpacity, aTransform,
   1061               aVisibleRect);
   1062 }
   1063 
   1064 template <typename Geometry>
   1065 void CompositorOGL::DrawGeometry(const Geometry& aGeometry,
   1066                                 const gfx::Rect& aRect,
   1067                                 const gfx::IntRect& aClipRect,
   1068                                 const EffectChain& aEffectChain,
   1069                                 gfx::Float aOpacity,
   1070                                 const gfx::Matrix4x4& aTransform,
   1071                                 const gfx::Rect& aVisibleRect) {
   1072  MOZ_ASSERT(mFrameInProgress, "frame not started");
   1073  MOZ_ASSERT(mCurrentRenderTarget, "No destination");
   1074 
   1075  MakeCurrent();
   1076 
   1077  // Convert aClipRect into render target space, and intersect it with the
   1078  // render target's clip.
   1079  IntRect clipRect = aClipRect + mCurrentRenderTarget->GetClipSpaceOrigin();
   1080  if (Maybe<IntRect> rtClip = mCurrentRenderTarget->GetClipRect()) {
   1081    clipRect = clipRect.Intersect(*rtClip);
   1082  }
   1083 
   1084  Rect destRect = aTransform.TransformAndClipBounds(
   1085      aRect, Rect(mCurrentRenderTarget->GetRect().Intersect(clipRect)));
   1086  if (destRect.IsEmpty()) {
   1087    return;
   1088  }
   1089 
   1090  // Move clipRect into device space.
   1091  IntPoint offset = mCurrentRenderTarget->GetOrigin();
   1092  clipRect -= offset;
   1093 
   1094  if (!mTarget && mCurrentRenderTarget->IsWindow()) {
   1095    clipRect.MoveBy(mSurfaceOrigin.x, -mSurfaceOrigin.y);
   1096  }
   1097 
   1098  ScopedGLState scopedScissorTestState(mGLContext, LOCAL_GL_SCISSOR_TEST, true);
   1099  ScopedScissorRect autoScissorRect(mGLContext, clipRect.X(),
   1100                                    FlipY(clipRect.Y() + clipRect.Height()),
   1101                                    clipRect.Width(), clipRect.Height());
   1102 
   1103  // Only apply DEAA to quads that have been transformed such that aliasing
   1104  // could be visible
   1105  bool bEnableAA = StaticPrefs::layers_deaa_enabled() &&
   1106                   !aTransform.Is2DIntegerTranslation();
   1107 
   1108  bool bRoundedClip = aEffectChain.mRoundedClipEffect;
   1109 
   1110  ShaderConfigOGL config =
   1111      GetShaderConfigFor(aEffectChain.mPrimaryEffect, bEnableAA, bRoundedClip);
   1112 
   1113  config.SetOpacity(aOpacity != 1.f);
   1114  ApplyPrimitiveConfig(config, aGeometry);
   1115 
   1116  ShaderProgramOGL* program = mProgramsHolder->ActivateProgram(config);
   1117  if (!program) {
   1118    return;
   1119  }
   1120  program->SetProjectionMatrix(mProjMatrix);
   1121  program->SetLayerTransform(aTransform);
   1122  program->SetRenderOffset(offset.x, offset.y);
   1123 
   1124  if (aOpacity != 1.f) program->SetLayerOpacity(aOpacity);
   1125 
   1126  if (config.mFeatures & ENABLE_TEXTURE_RECT) {
   1127    TextureSourceOGL* source = nullptr;
   1128    TexturedEffect* texturedEffect =
   1129        static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   1130    source = texturedEffect->mTexture->AsSourceOGL();
   1131    // This is used by IOSurface that use 0,0...w,h coordinate rather then
   1132    // 0,0..1,1.
   1133    program->SetTexCoordMultiplier(source->GetSize().width,
   1134                                   source->GetSize().height);
   1135  }
   1136 
   1137  if (aEffectChain.mRoundedClipEffect) {
   1138    program->SetRoundedClipRect(aEffectChain.mRoundedClipEffect->mRect);
   1139    program->SetRoundedClipRadii(aEffectChain.mRoundedClipEffect->mRadii);
   1140  }
   1141 
   1142  // XXX kip - These calculations could be performed once per layer rather than
   1143  //           for every tile.  This might belong in Compositor.cpp once DEAA
   1144  //           is implemented for DirectX.
   1145  if (bEnableAA) {
   1146    // Calculate the transformed vertices of aVisibleRect in screen space
   1147    // pixels, mirroring the calculations in the vertex shader
   1148    Matrix4x4 flatTransform = aTransform;
   1149    flatTransform.PostTranslate(-offset.x, -offset.y, 0.0f);
   1150    flatTransform *= mProjMatrix;
   1151 
   1152    Rect viewportClip = Rect(-1.0f, -1.0f, 2.0f, 2.0f);
   1153    size_t edgeCount = 0;
   1154    Point3D coefficients[4];
   1155 
   1156    Point points[Matrix4x4::kTransformAndClipRectMaxVerts];
   1157    size_t pointCount =
   1158        flatTransform.TransformAndClipRect(aVisibleRect, viewportClip, points);
   1159    for (size_t i = 0; i < pointCount; i++) {
   1160      points[i] = Point((points[i].x * 0.5f + 0.5f) * mViewportSize.width,
   1161                        (points[i].y * 0.5f + 0.5f) * mViewportSize.height);
   1162    }
   1163    if (pointCount > 2) {
   1164      // Use shoelace formula on a triangle in the clipped quad to determine if
   1165      // winding order is reversed.  Iterate through the triangles until one is
   1166      // found with a non-zero area.
   1167      float winding = 0.0f;
   1168      size_t wp = 0;
   1169      while (winding == 0.0f && wp < pointCount) {
   1170        int wp1 = (wp + 1) % pointCount;
   1171        int wp2 = (wp + 2) % pointCount;
   1172        winding = (points[wp1].x - points[wp].x).value *
   1173                      (points[wp1].y + points[wp].y).value +
   1174                  (points[wp2].x - points[wp1].x).value *
   1175                      (points[wp2].y + points[wp1].y).value +
   1176                  (points[wp].x - points[wp2].x).value *
   1177                      (points[wp].y + points[wp2].y).value;
   1178        wp++;
   1179      }
   1180      bool frontFacing = winding >= 0.0f;
   1181 
   1182      // Calculate the line coefficients used by the DEAA shader to determine
   1183      // the sub-pixel coverage of the edge pixels
   1184      for (size_t i = 0; i < pointCount; i++) {
   1185        const Point& p1 = points[i];
   1186        const Point& p2 = points[(i + 1) % pointCount];
   1187        // Create a DEAA edge for any non-straight lines, to a maximum of 4
   1188        if (p1.x != p2.x && p1.y != p2.y && edgeCount < 4) {
   1189          if (frontFacing) {
   1190            coefficients[edgeCount++] = GetLineCoefficients(p2, p1);
   1191          } else {
   1192            coefficients[edgeCount++] = GetLineCoefficients(p1, p2);
   1193          }
   1194        }
   1195      }
   1196    }
   1197 
   1198    // The coefficients that are not needed must not cull any fragments.
   1199    // We fill these unused coefficients with a clipping plane that has no
   1200    // effect.
   1201    for (size_t i = edgeCount; i < 4; i++) {
   1202      coefficients[i] = Point3D(0.0f, 1.0f, mViewportSize.height);
   1203    }
   1204 
   1205    // Set uniforms required by DEAA shader
   1206    Matrix4x4 transformInverted = aTransform;
   1207    transformInverted.Invert();
   1208    program->SetLayerTransformInverse(transformInverted);
   1209    program->SetDEAAEdges(coefficients);
   1210    program->SetVisibleCenter(aVisibleRect.Center());
   1211    program->SetViewportSize(mViewportSize);
   1212  }
   1213 
   1214  bool didSetBlendMode = false;
   1215 
   1216  switch (aEffectChain.mPrimaryEffect->mType) {
   1217    case EffectTypes::RGB: {
   1218      TexturedEffect* texturedEffect =
   1219          static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
   1220      TextureSource* source = texturedEffect->mTexture;
   1221 
   1222      didSetBlendMode = SetBlendMode(gl(), gfx::CompositionOp::OP_OVER,
   1223                                     texturedEffect->mPremultiplied);
   1224 
   1225      gfx::SamplingFilter samplingFilter = texturedEffect->mSamplingFilter;
   1226 
   1227      source->AsSourceOGL()->BindTexture(LOCAL_GL_TEXTURE0, samplingFilter);
   1228 
   1229      program->SetTextureUnit(0);
   1230 
   1231      Matrix4x4 textureTransform = source->AsSourceOGL()->GetTextureTransform();
   1232      program->SetTextureTransform(textureTransform);
   1233 
   1234      BindAndDrawGeometryWithTextureRect(
   1235          program, aGeometry, texturedEffect->mTextureCoords, source);
   1236      source->AsSourceOGL()->MaybeFenceTexture();
   1237    } break;
   1238    case EffectTypes::YCBCR: {
   1239      EffectYCbCr* effectYCbCr =
   1240          static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
   1241      TextureSource* sourceYCbCr = effectYCbCr->mTexture;
   1242      const int Y = 0, Cb = 1, Cr = 2;
   1243      TextureSourceOGL* sourceY = sourceYCbCr->GetSubSource(Y)->AsSourceOGL();
   1244      TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
   1245      TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
   1246 
   1247      if (!sourceY || !sourceCb || !sourceCr) {
   1248        NS_WARNING("Invalid layer texture.");
   1249        return;
   1250      }
   1251 
   1252      sourceY->BindTexture(LOCAL_GL_TEXTURE0, effectYCbCr->mSamplingFilter);
   1253      sourceCb->BindTexture(LOCAL_GL_TEXTURE1, effectYCbCr->mSamplingFilter);
   1254      sourceCr->BindTexture(LOCAL_GL_TEXTURE2, effectYCbCr->mSamplingFilter);
   1255 
   1256      if (config.mFeatures & ENABLE_TEXTURE_RECT) {
   1257        // This is used by IOSurface that use 0,0...w,h coordinate rather then
   1258        // 0,0..1,1.
   1259        program->SetCbCrTexCoordMultiplier(sourceCb->GetSize().width,
   1260                                           sourceCb->GetSize().height);
   1261      }
   1262 
   1263      program->SetYCbCrTextureUnits(Y, Cb, Cr);
   1264      program->SetTextureTransform(Matrix4x4());
   1265      program->SetYUVColorSpace(effectYCbCr->mYUVColorSpace);
   1266 
   1267      BindAndDrawGeometryWithTextureRect(program, aGeometry,
   1268                                         effectYCbCr->mTextureCoords,
   1269                                         sourceYCbCr->GetSubSource(Y));
   1270      sourceY->MaybeFenceTexture();
   1271      sourceCb->MaybeFenceTexture();
   1272      sourceCr->MaybeFenceTexture();
   1273    } break;
   1274    case EffectTypes::NV12: {
   1275      EffectNV12* effectNV12 =
   1276          static_cast<EffectNV12*>(aEffectChain.mPrimaryEffect.get());
   1277      TextureSource* sourceNV12 = effectNV12->mTexture;
   1278      const int Y = 0, CbCr = 1;
   1279      TextureSourceOGL* sourceY = sourceNV12->GetSubSource(Y)->AsSourceOGL();
   1280      TextureSourceOGL* sourceCbCr =
   1281          sourceNV12->GetSubSource(CbCr)->AsSourceOGL();
   1282 
   1283      if (!sourceY || !sourceCbCr) {
   1284        NS_WARNING("Invalid layer texture.");
   1285        return;
   1286      }
   1287 
   1288      sourceY->BindTexture(LOCAL_GL_TEXTURE0, effectNV12->mSamplingFilter);
   1289      sourceCbCr->BindTexture(LOCAL_GL_TEXTURE1, effectNV12->mSamplingFilter);
   1290 
   1291      if (config.mFeatures & ENABLE_TEXTURE_RECT) {
   1292        // This is used by IOSurface that use 0,0...w,h coordinate rather then
   1293        // 0,0..1,1.
   1294        program->SetCbCrTexCoordMultiplier(sourceCbCr->GetSize().width,
   1295                                           sourceCbCr->GetSize().height);
   1296      }
   1297 
   1298      program->SetNV12TextureUnits(Y, CbCr);
   1299      program->SetTextureTransform(Matrix4x4());
   1300      program->SetYUVColorSpace(effectNV12->mYUVColorSpace);
   1301 
   1302      BindAndDrawGeometryWithTextureRect(program, aGeometry,
   1303                                         effectNV12->mTextureCoords,
   1304                                         sourceNV12->GetSubSource(Y));
   1305      sourceY->MaybeFenceTexture();
   1306      sourceCbCr->MaybeFenceTexture();
   1307    } break;
   1308    default:
   1309      MOZ_ASSERT(false, "Unhandled effect type");
   1310      break;
   1311  }
   1312 
   1313  if (didSetBlendMode) {
   1314    gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
   1315                             LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
   1316  }
   1317 
   1318  // in case rendering has used some other GL context
   1319  MakeCurrent();
   1320 }
   1321 
   1322 void CompositorOGL::BindAndDrawGeometry(ShaderProgramOGL* aProgram,
   1323                                        const gfx::Rect& aRect) {
   1324  BindAndDrawQuad(aProgram, aRect);
   1325 }
   1326 
   1327 void CompositorOGL::BindAndDrawGeometry(
   1328    ShaderProgramOGL* aProgram,
   1329    const nsTArray<gfx::TexturedTriangle>& aTriangles) {
   1330  NS_ASSERTION(aProgram->HasInitialized(),
   1331               "Shader program not correctly initialized");
   1332 
   1333  const nsTArray<TexturedVertex> vertices =
   1334      TexturedTrianglesToVertexArray(aTriangles);
   1335 
   1336  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTriangleVBO);
   1337  mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER,
   1338                          vertices.Length() * sizeof(TexturedVertex),
   1339                          vertices.Elements(), LOCAL_GL_STREAM_DRAW);
   1340 
   1341  const GLsizei stride = 4 * sizeof(GLfloat);
   1342  InitializeVAO(kCoordinateAttributeIndex, 2, stride, 0);
   1343  InitializeVAO(kTexCoordinateAttributeIndex, 2, stride, 2 * sizeof(GLfloat));
   1344 
   1345  mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, vertices.Length());
   1346 
   1347  mGLContext->fDisableVertexAttribArray(kCoordinateAttributeIndex);
   1348  mGLContext->fDisableVertexAttribArray(kTexCoordinateAttributeIndex);
   1349  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
   1350 }
   1351 
   1352 // |aRect| is the rectangle we want to draw to. We will draw it with
   1353 // up to 4 draw commands if necessary to avoid wrapping.
   1354 // |aTexCoordRect| is the rectangle from the texture that we want to
   1355 // draw using the given program.
   1356 // |aTexture| is the texture we are drawing. Its actual size can be
   1357 // larger than the rectangle given by |texCoordRect|.
   1358 void CompositorOGL::BindAndDrawGeometryWithTextureRect(
   1359    ShaderProgramOGL* aProg, const Rect& aRect, const Rect& aTexCoordRect,
   1360    TextureSource* aTexture) {
   1361  Rect scaledTexCoordRect = GetTextureCoordinates(aTexCoordRect, aTexture);
   1362  Rect layerRects[4];
   1363  Rect textureRects[4];
   1364  size_t rects = DecomposeIntoNoRepeatRects(aRect, scaledTexCoordRect,
   1365                                            &layerRects, &textureRects);
   1366 
   1367  BindAndDrawQuads(aProg, rects, layerRects, textureRects);
   1368 }
   1369 
   1370 void CompositorOGL::BindAndDrawGeometryWithTextureRect(
   1371    ShaderProgramOGL* aProg, const nsTArray<gfx::TexturedTriangle>& aTriangles,
   1372    const gfx::Rect& aTexCoordRect, TextureSource* aTexture) {
   1373  BindAndDrawGeometry(aProg, aTriangles);
   1374 }
   1375 
   1376 void CompositorOGL::BindAndDrawQuads(ShaderProgramOGL* aProg, int aQuads,
   1377                                     const Rect* aLayerRects,
   1378                                     const Rect* aTextureRects) {
   1379  NS_ASSERTION(aProg->HasInitialized(),
   1380               "Shader program not correctly initialized");
   1381 
   1382  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
   1383  InitializeVAO(kCoordinateAttributeIndex, 4, 0, 0);
   1384 
   1385  aProg->SetLayerRects(aLayerRects);
   1386  if (aProg->GetTextureCount() > 0) {
   1387    aProg->SetTextureRects(aTextureRects);
   1388  }
   1389 
   1390  // We are using GL_TRIANGLES here because the Mac Intel drivers fail to
   1391  // properly process uniform arrays with GL_TRIANGLE_STRIP. Go figure.
   1392  mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6 * aQuads);
   1393  mGLContext->fDisableVertexAttribArray(kCoordinateAttributeIndex);
   1394  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
   1395 }
   1396 
   1397 void CompositorOGL::InitializeVAO(const GLuint aAttrib, const GLint aComponents,
   1398                                  const GLsizei aStride, const size_t aOffset) {
   1399  mGLContext->fVertexAttribPointer(aAttrib, aComponents, LOCAL_GL_FLOAT,
   1400                                   LOCAL_GL_FALSE, aStride,
   1401                                   reinterpret_cast<GLvoid*>(aOffset));
   1402  mGLContext->fEnableVertexAttribArray(aAttrib);
   1403 }
   1404 
   1405 #ifdef MOZ_DUMP_PAINTING
   1406 template <typename T>
   1407 void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf) {
   1408  if (gfxUtils::sDumpPaintFile != stderr) {
   1409    gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
   1410  } else {
   1411    nsCString uri = gfxUtils::GetAsDataURI(aSurf);
   1412    nsPrintfCString string(R"(array["%s-%)" PRIu64 R"("]="%s";\n)",
   1413                           aObj->Name(), uint64_t(aObj), uri.BeginReading());
   1414    fprintf_stderr(gfxUtils::sDumpPaintFile, "%s", string.get());
   1415  }
   1416 }
   1417 
   1418 void WriteSnapshotToDumpFile(Compositor* aCompositor, DrawTarget* aTarget) {
   1419  RefPtr<SourceSurface> surf = aTarget->Snapshot();
   1420  RefPtr<DataSourceSurface> dSurf = surf->GetDataSurface();
   1421  WriteSnapshotToDumpFile_internal(aCompositor, dSurf);
   1422 }
   1423 #endif
   1424 
   1425 void CompositorOGL::EndFrame() {
   1426  AUTO_PROFILER_LABEL("CompositorOGL::EndFrame", GRAPHICS);
   1427 
   1428 #ifdef MOZ_DUMP_PAINTING
   1429  if (gfxEnv::MOZ_DISABLE_FORCE_PRESENT()) {
   1430    LayoutDeviceIntSize size;
   1431    if (mUseExternalSurfaceSize) {
   1432      size = LayoutDeviceIntSize(mSurfaceSize.width, mSurfaceSize.height);
   1433    } else {
   1434      size = mWidget->GetClientSize();
   1435    }
   1436    RefPtr<DrawTarget> target =
   1437        gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
   1438            IntSize(size.width, size.height), SurfaceFormat::B8G8R8A8);
   1439    if (target) {
   1440      CopyToTarget(target, nsIntPoint(), Matrix());
   1441      WriteSnapshotToDumpFile(this, target);
   1442    }
   1443  }
   1444 #endif
   1445 
   1446  mFrameInProgress = false;
   1447  mShouldInvalidateWindow = false;
   1448 
   1449  if (mTarget) {
   1450    CopyToTarget(mTarget, mTargetBounds.TopLeft(), Matrix());
   1451    mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
   1452    mTarget = nullptr;
   1453    mWindowRenderTarget = nullptr;
   1454    mCurrentRenderTarget = nullptr;
   1455    Compositor::EndFrame();
   1456    return;
   1457  }
   1458 
   1459  mWindowRenderTarget = nullptr;
   1460  mCurrentRenderTarget = nullptr;
   1461 
   1462  if (mTexturePool) {
   1463    mTexturePool->EndFrame();
   1464  }
   1465 
   1466  InsertFrameDoneSync();
   1467 
   1468  mGLContext->SetDamage(mCurrentFrameInvalidRegion);
   1469  mGLContext->SwapBuffers();
   1470  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
   1471 
   1472  // Unbind all textures
   1473  for (GLuint i = 0; i <= 4; i++) {
   1474    mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
   1475    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
   1476    if (!mGLContext->IsGLES()) {
   1477      mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
   1478    }
   1479  }
   1480 
   1481  mCurrentFrameInvalidRegion.SetEmpty();
   1482 
   1483  Compositor::EndFrame();
   1484 }
   1485 
   1486 void CompositorOGL::InsertFrameDoneSync() {
   1487 #ifdef XP_MACOSX
   1488  // Only do this on macOS.
   1489  // On other platforms, SwapBuffers automatically applies back-pressure.
   1490  if (mThisFrameDoneSync) {
   1491    mGLContext->fDeleteSync(mThisFrameDoneSync);
   1492  }
   1493  mThisFrameDoneSync =
   1494      mGLContext->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
   1495 #elif defined(MOZ_WIDGET_ANDROID)
   1496  const auto& gle = gl::GLContextEGL::Cast(mGLContext);
   1497  const auto& egl = gle->mEgl;
   1498 
   1499  EGLSync sync = nullptr;
   1500  if (AndroidHardwareBufferApi::Get()) {
   1501    sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
   1502  }
   1503  if (sync) {
   1504    int fenceFd = egl->fDupNativeFenceFDANDROID(sync);
   1505    if (fenceFd >= 0) {
   1506      mReleaseFenceFd = ipc::FileDescriptor(UniqueFileHandle(fenceFd));
   1507    }
   1508    egl->fDestroySync(sync);
   1509    sync = nullptr;
   1510  }
   1511 #endif
   1512 }
   1513 
   1514 ipc::FileDescriptor CompositorOGL::GetReleaseFence() { return mReleaseFenceFd; }
   1515 
   1516 bool CompositorOGL::NeedToRecreateFullWindowRenderTarget() const {
   1517  if (!ShouldRecordFrames()) {
   1518    return false;
   1519  }
   1520  if (!mFullWindowRenderTarget) {
   1521    return true;
   1522  }
   1523  IntSize windowSize = mWidget->GetClientSize().ToUnknownSize();
   1524  return mFullWindowRenderTarget->GetSize() != windowSize;
   1525 }
   1526 
   1527 void CompositorOGL::SetDestinationSurfaceSize(const IntSize& aSize) {
   1528  mSurfaceSize.width = aSize.width;
   1529  mSurfaceSize.height = aSize.height;
   1530 }
   1531 
   1532 void CompositorOGL::CopyToTarget(DrawTarget* aTarget,
   1533                                 const nsIntPoint& aTopLeft,
   1534                                 const gfx::Matrix& aTransform) {
   1535  MOZ_ASSERT(aTarget);
   1536  IntRect rect;
   1537  if (mUseExternalSurfaceSize) {
   1538    rect = IntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
   1539  } else {
   1540    rect = IntRect(0, 0, mWidgetSize.width, mWidgetSize.height);
   1541  }
   1542  GLint width = rect.Width();
   1543  GLint height = rect.Height();
   1544 
   1545  if ((int64_t(width) * int64_t(height) * int64_t(4)) > INT32_MAX) {
   1546    NS_ERROR("Widget size too big - integer overflow!");
   1547    return;
   1548  }
   1549 
   1550  RefPtr<DataSourceSurface> source = Factory::CreateDataSourceSurface(
   1551      rect.Size(), gfx::SurfaceFormat::B8G8R8A8);
   1552  if (NS_WARN_IF(!source)) {
   1553    return;
   1554  }
   1555 
   1556  ReadPixelsIntoDataSurface(mGLContext, source);
   1557 
   1558  // Map from GL space to Cairo space and reverse the world transform.
   1559  Matrix glToCairoTransform = aTransform;
   1560  glToCairoTransform.Invert();
   1561  glToCairoTransform.PreScale(1.0, -1.0);
   1562  glToCairoTransform.PreTranslate(0.0, -height);
   1563 
   1564  glToCairoTransform.PostTranslate(-aTopLeft.x, -aTopLeft.y);
   1565 
   1566  Matrix oldMatrix = aTarget->GetTransform();
   1567  aTarget->SetTransform(glToCairoTransform);
   1568  Rect floatRect = Rect(rect.X(), rect.Y(), width, height);
   1569  aTarget->DrawSurface(source, floatRect, floatRect, DrawSurfaceOptions(),
   1570                       DrawOptions(1.0f, CompositionOp::OP_SOURCE));
   1571  aTarget->SetTransform(oldMatrix);
   1572  aTarget->Flush();
   1573 }
   1574 
   1575 void CompositorOGL::Pause() {
   1576 #ifdef MOZ_WIDGET_ANDROID
   1577  if (!gl() || gl()->IsDestroyed()) return;
   1578  // ReleaseSurface internally calls MakeCurrent
   1579  gl()->ReleaseSurface();
   1580 #elif defined(MOZ_WIDGET_GTK)
   1581  // ReleaseSurface internally calls MakeCurrent
   1582  gl()->ReleaseSurface();
   1583 #endif
   1584 }
   1585 
   1586 bool CompositorOGL::Resume() {
   1587 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) || \
   1588    defined(MOZ_WIDGET_GTK)
   1589  if (!gl() || gl()->IsDestroyed()) return false;
   1590 
   1591  // RenewSurface internally calls MakeCurrent.
   1592  return gl()->RenewSurface(GetWidget());
   1593 #else
   1594  return true;
   1595 #endif
   1596 }
   1597 
   1598 already_AddRefed<DataTextureSource> CompositorOGL::CreateDataTextureSource(
   1599    TextureFlags aFlags) {
   1600  if (!gl()) {
   1601    return nullptr;
   1602  }
   1603 
   1604  return MakeAndAddRef<TextureImageTextureSourceOGL>(this, aFlags);
   1605 }
   1606 
   1607 int32_t CompositorOGL::GetMaxTextureSize() const {
   1608  MOZ_ASSERT(mGLContext);
   1609  GLint texSize = 0;
   1610  mGLContext->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &texSize);
   1611  MOZ_ASSERT(texSize != 0);
   1612  return texSize;
   1613 }
   1614 
   1615 void CompositorOGL::MakeCurrent(MakeCurrentFlags aFlags) {
   1616  if (mDestroyed) {
   1617    NS_WARNING("Call on destroyed layer manager");
   1618    return;
   1619  }
   1620  mGLContext->MakeCurrent(aFlags & ForceMakeCurrent);
   1621 }
   1622 
   1623 GLuint CompositorOGL::GetTemporaryTexture(GLenum aTarget, GLenum aUnit) {
   1624  if (!mTexturePool) {
   1625    mTexturePool = new PerUnitTexturePoolOGL(gl());
   1626  }
   1627  return mTexturePool->GetTexture(aTarget, aUnit);
   1628 }
   1629 
   1630 GLuint PerUnitTexturePoolOGL::GetTexture(GLenum aTarget, GLenum aTextureUnit) {
   1631  if (mTextureTarget == 0) {
   1632    mTextureTarget = aTarget;
   1633  }
   1634  MOZ_ASSERT(mTextureTarget == aTarget);
   1635 
   1636  size_t index = aTextureUnit - LOCAL_GL_TEXTURE0;
   1637  // lazily grow the array of temporary textures
   1638  if (mTextures.Length() <= index) {
   1639    size_t prevLength = mTextures.Length();
   1640    mTextures.SetLength(index + 1);
   1641    for (unsigned int i = prevLength; i <= index; ++i) {
   1642      mTextures[i] = 0;
   1643    }
   1644  }
   1645  // lazily initialize the temporary textures
   1646  if (!mTextures[index]) {
   1647    if (!mGL->MakeCurrent()) {
   1648      return 0;
   1649    }
   1650    mGL->fGenTextures(1, &mTextures[index]);
   1651    mGL->fBindTexture(aTarget, mTextures[index]);
   1652    mGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_WRAP_S,
   1653                        LOCAL_GL_CLAMP_TO_EDGE);
   1654    mGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_WRAP_T,
   1655                        LOCAL_GL_CLAMP_TO_EDGE);
   1656  }
   1657  return mTextures[index];
   1658 }
   1659 
   1660 void PerUnitTexturePoolOGL::DestroyTextures() {
   1661  if (mGL && mGL->MakeCurrent()) {
   1662    if (mTextures.Length() > 0) {
   1663      mGL->fDeleteTextures(mTextures.Length(), &mTextures[0]);
   1664    }
   1665  }
   1666  mTextures.SetLength(0);
   1667 }
   1668 
   1669 void CompositorOGL::RegisterTextureSource(TextureSource* aTextureSource) {
   1670 #ifdef MOZ_WIDGET_GTK
   1671  if (mDestroyed) {
   1672    return;
   1673  }
   1674  mRegisteredTextureSources.insert(aTextureSource);
   1675 #endif
   1676 }
   1677 
   1678 void CompositorOGL::UnregisterTextureSource(TextureSource* aTextureSource) {
   1679 #ifdef MOZ_WIDGET_GTK
   1680  if (mDestroyed) {
   1681    return;
   1682  }
   1683  mRegisteredTextureSources.erase(aTextureSource);
   1684 #endif
   1685 }
   1686 
   1687 }  // namespace layers
   1688 }  // namespace mozilla