gfx/gl/GLBlitTextureImageHelper.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #include "GLBlitTextureImageHelper.h"
     8 #include "GLUploadHelpers.h"
     9 #include "DecomposeIntoNoRepeatTriangles.h"
    10 #include "GLContext.h"
    11 #include "ScopedGLHelpers.h"
    12 #include "nsRect.h"
    13 #include "gfx2DGlue.h"
    14 #include "gfxUtils.h"
    16 namespace mozilla {
    17 namespace gl {
    19 GLBlitTextureImageHelper::GLBlitTextureImageHelper(GLContext* gl)
    20     : mGL(gl)
    21     , mBlitProgram(0)
    22     , mBlitFramebuffer(0)
    24 {
    25 }
    27 GLBlitTextureImageHelper::~GLBlitTextureImageHelper()
    28 {
    29     // Likely used by OGL Layers.
    30     mGL->fDeleteProgram(mBlitProgram);
    31     mGL->fDeleteFramebuffers(1, &mBlitFramebuffer);
    32 }
    34 void
    35 GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
    36                                            TextureImage *aDst, const nsIntRect& aDstRect)
    37 {
    38     NS_ASSERTION(!aSrc->InUpdate(), "Source texture is in update!");
    39     NS_ASSERTION(!aDst->InUpdate(), "Destination texture is in update!");
    41     if (aSrcRect.IsEmpty() || aDstRect.IsEmpty())
    42         return;
    44     int savedFb = 0;
    45     mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
    47     ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, false);
    48     ScopedGLState scopedBlendState(mGL, LOCAL_GL_BLEND, false);
    50     // 2.0 means scale up by two
    51     float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
    52     float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
    54     // We start iterating over all destination tiles
    55     aDst->BeginTileIteration();
    56     do {
    57         // calculate portion of the tile that is going to be painted to
    58         nsIntRect dstSubRect;
    59         nsIntRect dstTextureRect = ThebesIntRect(aDst->GetTileRect());
    60         dstSubRect.IntersectRect(aDstRect, dstTextureRect);
    62         // this tile is not part of the destination rectangle aDstRect
    63         if (dstSubRect.IsEmpty())
    64             continue;
    66         // (*) transform the rect of this tile into the rectangle defined by aSrcRect...
    67         nsIntRect dstInSrcRect(dstSubRect);
    68         dstInSrcRect.MoveBy(-aDstRect.TopLeft());
    69         // ...which might be of different size, hence scale accordingly
    70         dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
    71         dstInSrcRect.MoveBy(aSrcRect.TopLeft());
    73         SetBlitFramebufferForDestTexture(aDst->GetTextureID());
    74         UseBlitProgram();
    76         aSrc->BeginTileIteration();
    77         // now iterate over all tiles in the source Image...
    78         do {
    79             // calculate portion of the source tile that is in the source rect
    80             nsIntRect srcSubRect;
    81             nsIntRect srcTextureRect = ThebesIntRect(aSrc->GetTileRect());
    82             srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
    84             // this tile is not part of the source rect
    85             if (srcSubRect.IsEmpty()) {
    86                 continue;
    87             }
    88             // calculate intersection of source rect with destination rect
    89             srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
    90             // this tile does not overlap the current destination tile
    91             if (srcSubRect.IsEmpty()) {
    92                 continue;
    93             }
    94             // We now have the intersection of
    95             //     the current source tile
    96             // and the desired source rectangle
    97             // and the destination tile
    98             // and the desired destination rectange
    99             // in destination space.
   100             // We need to transform this back into destination space, inverting the transform from (*)
   101             nsIntRect srcSubInDstRect(srcSubRect);
   102             srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
   103             srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
   104             srcSubInDstRect.MoveBy(aDstRect.TopLeft());
   106             // we transform these rectangles to be relative to the current src and dst tiles, respectively
   107             nsIntSize srcSize = srcTextureRect.Size();
   108             nsIntSize dstSize = dstTextureRect.Size();
   109             srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
   110             srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
   112             float dx0 = 2.0f * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0f;
   113             float dy0 = 2.0f * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0f;
   114             float dx1 = 2.0f * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0f;
   115             float dy1 = 2.0f * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0f;
   116             ScopedViewportRect autoViewportRect(mGL, 0, 0, dstSize.width, dstSize.height);
   118             RectTriangles rects;
   120             nsIntSize realTexSize = srcSize;
   121             if (!CanUploadNonPowerOfTwo(mGL)) {
   122                 realTexSize = nsIntSize(gfx::NextPowerOfTwo(srcSize.width),
   123                                         gfx::NextPowerOfTwo(srcSize.height));
   124             }
   126             if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
   127                 rects.addRect(/* dest rectangle */
   128                         dx0, dy0, dx1, dy1,
   129                         /* tex coords */
   130                         srcSubRect.x / float(realTexSize.width),
   131                         srcSubRect.y / float(realTexSize.height),
   132                         srcSubRect.XMost() / float(realTexSize.width),
   133                         srcSubRect.YMost() / float(realTexSize.height));
   134             } else {
   135                 DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
   137                 // now put the coords into the d[xy]0 .. d[xy]1 coordinate space
   138                 // from the 0..1 that it comes out of decompose
   139                 InfallibleTArray<RectTriangles::coord>& coords = rects.vertCoords();
   141                 for (unsigned int i = 0; i < coords.Length(); ++i) {
   142                     coords[i].x = (coords[i].x * (dx1 - dx0)) + dx0;
   143                     coords[i].y = (coords[i].y * (dy1 - dy0)) + dy0;
   144                 }
   145             }
   147             ScopedBindTextureUnit autoTexUnit(mGL, LOCAL_GL_TEXTURE0);
   148             ScopedBindTexture autoTex(mGL, aSrc->GetTextureID());
   150             mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
   152             mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertCoords().Elements());
   153             mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoords().Elements());
   155             mGL->fEnableVertexAttribArray(0);
   156             mGL->fEnableVertexAttribArray(1);
   158             mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
   160             mGL->fDisableVertexAttribArray(0);
   161             mGL->fDisableVertexAttribArray(1);
   163         } while (aSrc->NextTile());
   164     } while (aDst->NextTile());
   166     mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
   167     mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
   169     // unbind the previous texture from the framebuffer
   170     SetBlitFramebufferForDestTexture(0);
   172     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
   173 }
   175 void
   176 GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(GLuint aTexture)
   177 {
   178     if (!mBlitFramebuffer) {
   179         mGL->fGenFramebuffers(1, &mBlitFramebuffer);
   180     }
   182     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
   183     mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
   184                                LOCAL_GL_COLOR_ATTACHMENT0,
   185                                LOCAL_GL_TEXTURE_2D,
   186                                aTexture,
   187                                0);
   189     GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
   190     if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
   191         nsAutoCString msg;
   192         msg.Append("Framebuffer not complete -- error 0x");
   193         msg.AppendInt(result, 16);
   194         // Note: if you are hitting this, it is likely that
   195         // your texture is not texture complete -- that is, you
   196         // allocated a texture name, but didn't actually define its
   197         // size via a call to TexImage2D.
   198         NS_RUNTIMEABORT(msg.get());
   199     }
   200 }
   202 void
   203 GLBlitTextureImageHelper::UseBlitProgram()
   204 {
   205     if (mBlitProgram) {
   206         mGL->fUseProgram(mBlitProgram);
   207         return;
   208     }
   210     mBlitProgram = mGL->fCreateProgram();
   212     GLuint shaders[2];
   213     shaders[0] = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
   214     shaders[1] = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
   216     const char *blitVSSrc =
   217         "attribute vec2 aVertex;"
   218         "attribute vec2 aTexCoord;"
   219         "varying vec2 vTexCoord;"
   220         "void main() {"
   221         "  vTexCoord = aTexCoord;"
   222         "  gl_Position = vec4(aVertex, 0.0, 1.0);"
   223         "}";
   224     const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
   225         "uniform sampler2D uSrcTexture;"
   226         "varying vec2 vTexCoord;"
   227         "void main() {"
   228         "  gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
   229         "}";
   231     mGL->fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, nullptr);
   232     mGL->fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, nullptr);
   234     for (int i = 0; i < 2; ++i) {
   235         GLint success, len = 0;
   237         mGL->fCompileShader(shaders[i]);
   238         mGL->fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
   239         NS_ASSERTION(success, "Shader compilation failed!");
   241         if (!success) {
   242             nsAutoCString log;
   243             mGL->fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
   244             log.SetCapacity(len);
   245             mGL->fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
   246             log.SetLength(len);
   248             printf_stderr("Shader %d compilation failed:\n%s\n", i, log.get());
   249             return;
   250         }
   252         mGL->fAttachShader(mBlitProgram, shaders[i]);
   253         mGL->fDeleteShader(shaders[i]);
   254     }
   256     mGL->fBindAttribLocation(mBlitProgram, 0, "aVertex");
   257     mGL->fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
   259     mGL->fLinkProgram(mBlitProgram);
   261     GLint success, len = 0;
   262     mGL->fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
   263     NS_ASSERTION(success, "Shader linking failed!");
   265     if (!success) {
   266         nsAutoCString log;
   267         mGL->fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
   268         log.SetCapacity(len);
   269         mGL->fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
   270         log.SetLength(len);
   272         printf_stderr("Program linking failed:\n%s\n", log.get());
   273         return;
   274     }
   276     mGL->fUseProgram(mBlitProgram);
   277     mGL->fUniform1i(mGL->fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
   278 }
   280 }
   281 }

mercurial