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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "GLBlitTextureImageHelper.h"
       8             : #include "GLUploadHelpers.h"
       9             : #include "DecomposeIntoNoRepeatTriangles.h"
      10             : #include "GLContext.h"
      11             : #include "GLTextureImage.h"
      12             : #include "ScopedGLHelpers.h"
      13             : #include "nsRect.h"
      14             : #include "gfx2DGlue.h"
      15             : #include "gfxUtils.h"
      16             : #include "CompositorOGL.h"
      17             : #include "mozilla/gfx/Point.h"
      18             : 
      19             : using namespace mozilla::gl;
      20             : 
      21             : namespace mozilla {
      22             : namespace layers {
      23             : 
      24           0 : GLBlitTextureImageHelper::GLBlitTextureImageHelper(CompositorOGL* aCompositor)
      25             :     : mCompositor(aCompositor)
      26             :     , mBlitProgram(0)
      27           0 :     , mBlitFramebuffer(0)
      28             : 
      29             : {
      30           0 : }
      31             : 
      32           0 : GLBlitTextureImageHelper::~GLBlitTextureImageHelper()
      33             : {
      34           0 :     GLContext *gl = mCompositor->gl();
      35             :     // Likely used by OGL Layers.
      36           0 :     gl->fDeleteProgram(mBlitProgram);
      37           0 :     gl->fDeleteFramebuffers(1, &mBlitFramebuffer);
      38           0 : }
      39             : 
      40             : void
      41           0 : GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const gfx::IntRect& aSrcRect,
      42             :                                            TextureImage *aDst, const gfx::IntRect& aDstRect)
      43             : {
      44           0 :     GLContext *gl = mCompositor->gl();
      45             : 
      46           0 :     if (!aSrc || !aDst || aSrcRect.IsEmpty() || aDstRect.IsEmpty())
      47           0 :         return;
      48             : 
      49           0 :     int savedFb = 0;
      50           0 :     gl->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
      51             : 
      52           0 :     ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST, false);
      53           0 :     ScopedGLState scopedBlendState(gl, LOCAL_GL_BLEND, false);
      54             : 
      55             :     // 2.0 means scale up by two
      56           0 :     float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
      57           0 :     float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
      58             : 
      59             :     // We start iterating over all destination tiles
      60           0 :     aDst->BeginBigImageIteration();
      61           0 :     do {
      62             :         // calculate portion of the tile that is going to be painted to
      63           0 :         gfx::IntRect dstSubRect;
      64           0 :         gfx::IntRect dstTextureRect = aDst->GetTileRect();
      65           0 :         dstSubRect.IntersectRect(aDstRect, dstTextureRect);
      66             : 
      67             :         // this tile is not part of the destination rectangle aDstRect
      68           0 :         if (dstSubRect.IsEmpty())
      69           0 :             continue;
      70             : 
      71             :         // (*) transform the rect of this tile into the rectangle defined by aSrcRect...
      72           0 :         gfx::IntRect dstInSrcRect(dstSubRect);
      73           0 :         dstInSrcRect.MoveBy(-aDstRect.TopLeft());
      74             :         // ...which might be of different size, hence scale accordingly
      75           0 :         dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
      76           0 :         dstInSrcRect.MoveBy(aSrcRect.TopLeft());
      77             : 
      78           0 :         SetBlitFramebufferForDestTexture(aDst->GetTextureID());
      79           0 :         UseBlitProgram();
      80             : 
      81           0 :         aSrc->BeginBigImageIteration();
      82             :         // now iterate over all tiles in the source Image...
      83           0 :         do {
      84             :             // calculate portion of the source tile that is in the source rect
      85           0 :             gfx::IntRect srcSubRect;
      86           0 :             gfx::IntRect srcTextureRect = aSrc->GetTileRect();
      87           0 :             srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
      88             : 
      89             :             // this tile is not part of the source rect
      90           0 :             if (srcSubRect.IsEmpty()) {
      91           0 :                 continue;
      92             :             }
      93             :             // calculate intersection of source rect with destination rect
      94           0 :             srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
      95             :             // this tile does not overlap the current destination tile
      96           0 :             if (srcSubRect.IsEmpty()) {
      97           0 :                 continue;
      98             :             }
      99             :             // We now have the intersection of
     100             :             //     the current source tile
     101             :             // and the desired source rectangle
     102             :             // and the destination tile
     103             :             // and the desired destination rectange
     104             :             // in destination space.
     105             :             // We need to transform this back into destination space, inverting the transform from (*)
     106           0 :             gfx::IntRect srcSubInDstRect(srcSubRect);
     107           0 :             srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
     108           0 :             srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
     109           0 :             srcSubInDstRect.MoveBy(aDstRect.TopLeft());
     110             : 
     111             :             // we transform these rectangles to be relative to the current src and dst tiles, respectively
     112           0 :             gfx::IntSize srcSize = srcTextureRect.Size();
     113           0 :             gfx::IntSize dstSize = dstTextureRect.Size();
     114           0 :             srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
     115           0 :             srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
     116             : 
     117           0 :             float dx0 = 2.0f * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0f;
     118           0 :             float dy0 = 2.0f * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0f;
     119           0 :             float dx1 = 2.0f * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0f;
     120           0 :             float dy1 = 2.0f * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0f;
     121           0 :             ScopedViewportRect autoViewportRect(gl, 0, 0, dstSize.width, dstSize.height);
     122             : 
     123           0 :             RectTriangles rects;
     124             : 
     125           0 :             gfx::IntSize realTexSize = srcSize;
     126           0 :             if (!CanUploadNonPowerOfTwo(gl)) {
     127           0 :                 realTexSize = gfx::IntSize(RoundUpPow2(srcSize.width),
     128           0 :                                            RoundUpPow2(srcSize.height));
     129             :             }
     130             : 
     131           0 :             if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
     132           0 :                 rects.addRect(/* dest rectangle */
     133             :                         dx0, dy0, dx1, dy1,
     134             :                         /* tex coords */
     135           0 :                         srcSubRect.x / float(realTexSize.width),
     136           0 :                         srcSubRect.y / float(realTexSize.height),
     137           0 :                         srcSubRect.XMost() / float(realTexSize.width),
     138           0 :                         srcSubRect.YMost() / float(realTexSize.height));
     139             :             } else {
     140           0 :                 DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
     141             : 
     142             :                 // now put the coords into the d[xy]0 .. d[xy]1 coordinate space
     143             :                 // from the 0..1 that it comes out of decompose
     144           0 :                 InfallibleTArray<RectTriangles::coord>& coords = rects.vertCoords();
     145             : 
     146           0 :                 for (unsigned int i = 0; i < coords.Length(); ++i) {
     147           0 :                     coords[i].x = (coords[i].x * (dx1 - dx0)) + dx0;
     148           0 :                     coords[i].y = (coords[i].y * (dy1 - dy0)) + dy0;
     149             :                 }
     150             :             }
     151             : 
     152           0 :             ScopedBindTextureUnit autoTexUnit(gl, LOCAL_GL_TEXTURE0);
     153           0 :             ScopedBindTexture autoTex(gl, aSrc->GetTextureID());
     154           0 :             ScopedVertexAttribPointer autoAttrib0(gl, 0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, rects.vertCoords().Elements());
     155           0 :             ScopedVertexAttribPointer autoAttrib1(gl, 1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0, rects.texCoords().Elements());
     156             : 
     157           0 :             gl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
     158             : 
     159           0 :         } while (aSrc->NextTile());
     160           0 :     } while (aDst->NextTile());
     161             : 
     162             :     // unbind the previous texture from the framebuffer
     163           0 :     SetBlitFramebufferForDestTexture(0);
     164             : 
     165           0 :     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
     166             : }
     167             : 
     168             : void
     169           0 : GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(GLuint aTexture)
     170             : {
     171           0 :     GLContext *gl = mCompositor->gl();
     172           0 :     if (!mBlitFramebuffer) {
     173           0 :         gl->fGenFramebuffers(1, &mBlitFramebuffer);
     174             :     }
     175             : 
     176           0 :     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
     177             :     gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
     178             :                                LOCAL_GL_COLOR_ATTACHMENT0,
     179             :                                LOCAL_GL_TEXTURE_2D,
     180             :                                aTexture,
     181           0 :                                0);
     182             : 
     183           0 :     GLenum result = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
     184           0 :     if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
     185           0 :         nsAutoCString msg;
     186           0 :         msg.AppendLiteral("Framebuffer not complete -- error 0x");
     187           0 :         msg.AppendInt(result, 16);
     188             :         // Note: if you are hitting this, it is likely that
     189             :         // your texture is not texture complete -- that is, you
     190             :         // allocated a texture name, but didn't actually define its
     191             :         // size via a call to TexImage2D.
     192           0 :         NS_RUNTIMEABORT(msg.get());
     193             :     }
     194           0 : }
     195             : 
     196             : void
     197           0 : GLBlitTextureImageHelper::UseBlitProgram()
     198             : {
     199             :     // XXX: GLBlitTextureImageHelper doesn't use ShaderProgramOGL
     200             :     // so we need to Reset the program
     201           0 :     mCompositor->ResetProgram();
     202             : 
     203           0 :     GLContext *gl = mCompositor->gl();
     204           0 :     if (mBlitProgram) {
     205           0 :         gl->fUseProgram(mBlitProgram);
     206           0 :         return;
     207             :     }
     208             : 
     209           0 :     mBlitProgram = gl->fCreateProgram();
     210             : 
     211             :     GLuint shaders[2];
     212           0 :     shaders[0] = gl->fCreateShader(LOCAL_GL_VERTEX_SHADER);
     213           0 :     shaders[1] = gl->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
     214             : 
     215             :     const char *blitVSSrc =
     216             :         "attribute vec2 aVertex;"
     217             :         "attribute vec2 aTexCoord;"
     218             :         "varying vec2 vTexCoord;"
     219             :         "void main() {"
     220             :         "  vTexCoord = aTexCoord;"
     221             :         "  gl_Position = vec4(aVertex, 0.0, 1.0);"
     222           0 :         "}";
     223             :     const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
     224             :         "uniform sampler2D uSrcTexture;"
     225             :         "varying vec2 vTexCoord;"
     226             :         "void main() {"
     227             :         "  gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
     228           0 :         "}";
     229             : 
     230           0 :     gl->fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, nullptr);
     231           0 :     gl->fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, nullptr);
     232             : 
     233           0 :     for (int i = 0; i < 2; ++i) {
     234           0 :         GLint success, len = 0;
     235             : 
     236           0 :         gl->fCompileShader(shaders[i]);
     237           0 :         gl->fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
     238           0 :         NS_ASSERTION(success, "Shader compilation failed!");
     239             : 
     240           0 :         if (!success) {
     241           0 :             nsAutoCString log;
     242           0 :             gl->fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
     243           0 :             log.SetCapacity(len);
     244           0 :             gl->fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
     245           0 :             log.SetLength(len);
     246             : 
     247           0 :             printf_stderr("Shader %d compilation failed:\n%s\n", i, log.get());
     248           0 :             return;
     249             :         }
     250             : 
     251           0 :         gl->fAttachShader(mBlitProgram, shaders[i]);
     252           0 :         gl->fDeleteShader(shaders[i]);
     253             :     }
     254             : 
     255           0 :     gl->fBindAttribLocation(mBlitProgram, 0, "aVertex");
     256           0 :     gl->fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
     257             : 
     258           0 :     gl->fLinkProgram(mBlitProgram);
     259             : 
     260           0 :     GLint success, len = 0;
     261           0 :     gl->fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
     262           0 :     NS_ASSERTION(success, "Shader linking failed!");
     263             : 
     264           0 :     if (!success) {
     265           0 :         nsAutoCString log;
     266           0 :         gl->fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
     267           0 :         log.SetCapacity(len);
     268           0 :         gl->fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
     269           0 :         log.SetLength(len);
     270             : 
     271           0 :         printf_stderr("Program linking failed:\n%s\n", log.get());
     272           0 :         return;
     273             :     }
     274             : 
     275           0 :     gl->fUseProgram(mBlitProgram);
     276           0 :     gl->fUniform1i(gl->fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
     277             : }
     278             : 
     279             : } // namespace layers
     280             : } // namespace mozilla

Generated by: LCOV version 1.13