LCOV - code coverage report
Current view: top level - gfx/layers/opengl - CompositorOGL.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 847 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 51 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13