зеркало из https://github.com/mozilla/gecko-dev.git
Bug 942503 - Move BlitTextureImage out of GLContext - r=jgilbert
This commit is contained in:
Родитель
cbc3e900a8
Коммит
1095b2aa48
|
@ -0,0 +1,281 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
#include "GLContext.h"
|
||||
#include "nsRect.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
GLBlitTextureImageHelper::GLBlitTextureImageHelper(GLContext* gl)
|
||||
: mGL(gl)
|
||||
, mBlitProgram(0)
|
||||
, mBlitFramebuffer(0)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
GLBlitTextureImageHelper::~GLBlitTextureImageHelper()
|
||||
{
|
||||
// Likely used by OGL Layers.
|
||||
mGL->fDeleteProgram(mBlitProgram);
|
||||
mGL->fDeleteFramebuffers(1, &mBlitFramebuffer);
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
TextureImage *aDst, const nsIntRect& aDstRect)
|
||||
{
|
||||
NS_ASSERTION(!aSrc->InUpdate(), "Source texture is in update!");
|
||||
NS_ASSERTION(!aDst->InUpdate(), "Destination texture is in update!");
|
||||
|
||||
if (aSrcRect.IsEmpty() || aDstRect.IsEmpty())
|
||||
return;
|
||||
|
||||
int savedFb = 0;
|
||||
mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
|
||||
|
||||
mGL->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
mGL->fDisable(LOCAL_GL_BLEND);
|
||||
|
||||
// 2.0 means scale up by two
|
||||
float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
|
||||
float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
|
||||
|
||||
// We start iterating over all destination tiles
|
||||
aDst->BeginTileIteration();
|
||||
do {
|
||||
// calculate portion of the tile that is going to be painted to
|
||||
nsIntRect dstSubRect;
|
||||
nsIntRect dstTextureRect = ThebesIntRect(aDst->GetTileRect());
|
||||
dstSubRect.IntersectRect(aDstRect, dstTextureRect);
|
||||
|
||||
// this tile is not part of the destination rectangle aDstRect
|
||||
if (dstSubRect.IsEmpty())
|
||||
continue;
|
||||
|
||||
// (*) transform the rect of this tile into the rectangle defined by aSrcRect...
|
||||
nsIntRect dstInSrcRect(dstSubRect);
|
||||
dstInSrcRect.MoveBy(-aDstRect.TopLeft());
|
||||
// ...which might be of different size, hence scale accordingly
|
||||
dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
|
||||
dstInSrcRect.MoveBy(aSrcRect.TopLeft());
|
||||
|
||||
SetBlitFramebufferForDestTexture(aDst->GetTextureID());
|
||||
UseBlitProgram();
|
||||
|
||||
aSrc->BeginTileIteration();
|
||||
// now iterate over all tiles in the source Image...
|
||||
do {
|
||||
// calculate portion of the source tile that is in the source rect
|
||||
nsIntRect srcSubRect;
|
||||
nsIntRect srcTextureRect = ThebesIntRect(aSrc->GetTileRect());
|
||||
srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
|
||||
|
||||
// this tile is not part of the source rect
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// calculate intersection of source rect with destination rect
|
||||
srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
|
||||
// this tile does not overlap the current destination tile
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// We now have the intersection of
|
||||
// the current source tile
|
||||
// and the desired source rectangle
|
||||
// and the destination tile
|
||||
// and the desired destination rectange
|
||||
// in destination space.
|
||||
// We need to transform this back into destination space, inverting the transform from (*)
|
||||
nsIntRect srcSubInDstRect(srcSubRect);
|
||||
srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
|
||||
srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
|
||||
srcSubInDstRect.MoveBy(aDstRect.TopLeft());
|
||||
|
||||
// we transform these rectangles to be relative to the current src and dst tiles, respectively
|
||||
nsIntSize srcSize = srcTextureRect.Size();
|
||||
nsIntSize dstSize = dstTextureRect.Size();
|
||||
srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
|
||||
srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
|
||||
|
||||
float dx0 = 2.0f * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0f;
|
||||
float dy0 = 2.0f * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0f;
|
||||
float dx1 = 2.0f * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0f;
|
||||
float dy1 = 2.0f * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0f;
|
||||
mGL->PushViewportRect(nsIntRect(0, 0, dstSize.width, dstSize.height));
|
||||
|
||||
RectTriangles rects;
|
||||
|
||||
nsIntSize realTexSize = srcSize;
|
||||
if (!mGL->CanUploadNonPowerOfTwo()) {
|
||||
realTexSize = nsIntSize(gfx::NextPowerOfTwo(srcSize.width),
|
||||
gfx::NextPowerOfTwo(srcSize.height));
|
||||
}
|
||||
|
||||
if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
|
||||
rects.addRect(/* dest rectangle */
|
||||
dx0, dy0, dx1, dy1,
|
||||
/* tex coords */
|
||||
srcSubRect.x / float(realTexSize.width),
|
||||
srcSubRect.y / float(realTexSize.height),
|
||||
srcSubRect.XMost() / float(realTexSize.width),
|
||||
srcSubRect.YMost() / float(realTexSize.height));
|
||||
} else {
|
||||
DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
|
||||
|
||||
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
|
||||
// from the 0..1 that it comes out of decompose
|
||||
RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
|
||||
|
||||
for (unsigned int i = 0; i < rects.elements(); ++i) {
|
||||
v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
|
||||
v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
|
||||
}
|
||||
}
|
||||
|
||||
TextureImage::ScopedBindTexture texBind(aSrc, LOCAL_GL_TEXTURE0);
|
||||
|
||||
mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
|
||||
mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
|
||||
mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
|
||||
|
||||
mGL->fEnableVertexAttribArray(0);
|
||||
mGL->fEnableVertexAttribArray(1);
|
||||
|
||||
mGL->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
|
||||
|
||||
mGL->fDisableVertexAttribArray(0);
|
||||
mGL->fDisableVertexAttribArray(1);
|
||||
|
||||
mGL->PopViewportRect();
|
||||
} while (aSrc->NextTile());
|
||||
} while (aDst->NextTile());
|
||||
|
||||
mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
|
||||
mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
|
||||
|
||||
// unbind the previous texture from the framebuffer
|
||||
SetBlitFramebufferForDestTexture(0);
|
||||
|
||||
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
|
||||
|
||||
mGL->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
mGL->fEnable(LOCAL_GL_BLEND);
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(GLuint aTexture)
|
||||
{
|
||||
if (!mBlitFramebuffer) {
|
||||
mGL->fGenFramebuffers(1, &mBlitFramebuffer);
|
||||
}
|
||||
|
||||
mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
|
||||
mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
aTexture,
|
||||
0);
|
||||
|
||||
GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
|
||||
nsAutoCString msg;
|
||||
msg.Append("Framebuffer not complete -- error 0x");
|
||||
msg.AppendInt(result, 16);
|
||||
// Note: if you are hitting this, it is likely that
|
||||
// your texture is not texture complete -- that is, you
|
||||
// allocated a texture name, but didn't actually define its
|
||||
// size via a call to TexImage2D.
|
||||
NS_RUNTIMEABORT(msg.get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLBlitTextureImageHelper::UseBlitProgram()
|
||||
{
|
||||
if (mBlitProgram) {
|
||||
mGL->fUseProgram(mBlitProgram);
|
||||
return;
|
||||
}
|
||||
|
||||
mBlitProgram = mGL->fCreateProgram();
|
||||
|
||||
GLuint shaders[2];
|
||||
shaders[0] = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
shaders[1] = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
|
||||
const char *blitVSSrc =
|
||||
"attribute vec2 aVertex;"
|
||||
"attribute vec2 aTexCoord;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" vTexCoord = aTexCoord;"
|
||||
" gl_Position = vec4(aVertex, 0.0, 1.0);"
|
||||
"}";
|
||||
const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
|
||||
"uniform sampler2D uSrcTexture;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
|
||||
"}";
|
||||
|
||||
mGL->fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, nullptr);
|
||||
mGL->fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, nullptr);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
GLint success, len = 0;
|
||||
|
||||
mGL->fCompileShader(shaders[i]);
|
||||
mGL->fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader compilation failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
mGL->fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Shader %d compilation failed:\n%s\n", log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
mGL->fAttachShader(mBlitProgram, shaders[i]);
|
||||
mGL->fDeleteShader(shaders[i]);
|
||||
}
|
||||
|
||||
mGL->fBindAttribLocation(mBlitProgram, 0, "aVertex");
|
||||
mGL->fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
|
||||
|
||||
mGL->fLinkProgram(mBlitProgram);
|
||||
|
||||
GLint success, len = 0;
|
||||
mGL->fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader linking failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
mGL->fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
mGL->fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Program linking failed:\n%s\n", log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
mGL->fUseProgram(mBlitProgram);
|
||||
mGL->fUniform1i(mGL->fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GLBLITTEXTUREIMAGEHELPER_H_
|
||||
#define GLBLITTEXTUREIMAGEHELPER_H_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLConsts.h"
|
||||
|
||||
struct nsIntRect;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
class GLContext;
|
||||
class TextureImage;
|
||||
|
||||
class GLBlitTextureImageHelper MOZ_FINAL
|
||||
{
|
||||
// The GLContext is the sole owner of the GLBlitTextureImageHelper.
|
||||
GLContext* mGL;
|
||||
|
||||
// lazy-initialized things
|
||||
GLuint mBlitProgram, mBlitFramebuffer;
|
||||
void UseBlitProgram();
|
||||
void SetBlitFramebufferForDestTexture(GLuint aTexture);
|
||||
|
||||
public:
|
||||
|
||||
GLBlitTextureImageHelper(GLContext *gl);
|
||||
~GLBlitTextureImageHelper();
|
||||
|
||||
/**
|
||||
* Copy a rectangle from one TextureImage into another. The
|
||||
* source and destination are given in integer coordinates, and
|
||||
* will be converted to texture coordinates.
|
||||
*
|
||||
* For the source texture, the wrap modes DO apply -- it's valid
|
||||
* to use REPEAT or PAD and expect appropriate behaviour if the source
|
||||
* rectangle extends beyond its bounds.
|
||||
*
|
||||
* For the destination texture, the wrap modes DO NOT apply -- the
|
||||
* destination will be clipped by the bounds of the texture.
|
||||
*
|
||||
* Note: calling this function will cause the following OpenGL state
|
||||
* to be changed:
|
||||
*
|
||||
* - current program
|
||||
* - framebuffer binding
|
||||
* - viewport
|
||||
* - blend state (will be enabled at end)
|
||||
* - scissor state (will be enabled at end)
|
||||
* - vertex attrib 0 and 1 (pointer and enable state [enable state will be disabled at exit])
|
||||
* - array buffer binding (will be 0)
|
||||
* - active texture (will be 0)
|
||||
* - texture 0 binding
|
||||
*/
|
||||
void BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
TextureImage *aDst, const nsIntRect& aDstRect);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLBLITTEXTUREIMAGEHELPER_H_
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "GLContext.h"
|
||||
#include "GLBlitHelper.h"
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
@ -260,8 +261,6 @@ GLContext::GLContext(const SurfaceCaps& caps,
|
|||
#endif
|
||||
mSharedContext(sharedContext),
|
||||
mFlipped(false),
|
||||
mBlitProgram(0),
|
||||
mBlitFramebuffer(0),
|
||||
mCaps(caps),
|
||||
mScreen(nullptr),
|
||||
mLockedSurface(nullptr),
|
||||
|
@ -1853,12 +1852,7 @@ GLContext::MarkDestroyed()
|
|||
DestroyScreenBuffer();
|
||||
|
||||
mBlitHelper = nullptr;
|
||||
|
||||
// Likely used by OGL Layers.
|
||||
fDeleteProgram(mBlitProgram);
|
||||
mBlitProgram = 0;
|
||||
fDeleteFramebuffers(1, &mBlitFramebuffer);
|
||||
mBlitFramebuffer = 0;
|
||||
mBlitTextureImageHelper = nullptr;
|
||||
|
||||
mTexGarbageBin->GLContextTeardown();
|
||||
} else {
|
||||
|
@ -2324,150 +2318,6 @@ GLContext::ReadPixelsIntoImageSurface(gfxImageSurface* dest)
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
TextureImage *aDst, const nsIntRect& aDstRect)
|
||||
{
|
||||
NS_ASSERTION(!aSrc->InUpdate(), "Source texture is in update!");
|
||||
NS_ASSERTION(!aDst->InUpdate(), "Destination texture is in update!");
|
||||
|
||||
if (aSrcRect.IsEmpty() || aDstRect.IsEmpty())
|
||||
return;
|
||||
|
||||
int savedFb = 0;
|
||||
fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
|
||||
|
||||
fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
fDisable(LOCAL_GL_BLEND);
|
||||
|
||||
// 2.0 means scale up by two
|
||||
float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
|
||||
float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
|
||||
|
||||
// We start iterating over all destination tiles
|
||||
aDst->BeginTileIteration();
|
||||
do {
|
||||
// calculate portion of the tile that is going to be painted to
|
||||
nsIntRect dstSubRect;
|
||||
nsIntRect dstTextureRect = ThebesIntRect(aDst->GetTileRect());
|
||||
dstSubRect.IntersectRect(aDstRect, dstTextureRect);
|
||||
|
||||
// this tile is not part of the destination rectangle aDstRect
|
||||
if (dstSubRect.IsEmpty())
|
||||
continue;
|
||||
|
||||
// (*) transform the rect of this tile into the rectangle defined by aSrcRect...
|
||||
nsIntRect dstInSrcRect(dstSubRect);
|
||||
dstInSrcRect.MoveBy(-aDstRect.TopLeft());
|
||||
// ...which might be of different size, hence scale accordingly
|
||||
dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
|
||||
dstInSrcRect.MoveBy(aSrcRect.TopLeft());
|
||||
|
||||
SetBlitFramebufferForDestTexture(aDst->GetTextureID());
|
||||
UseBlitProgram();
|
||||
|
||||
aSrc->BeginTileIteration();
|
||||
// now iterate over all tiles in the source Image...
|
||||
do {
|
||||
// calculate portion of the source tile that is in the source rect
|
||||
nsIntRect srcSubRect;
|
||||
nsIntRect srcTextureRect = ThebesIntRect(aSrc->GetTileRect());
|
||||
srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
|
||||
|
||||
// this tile is not part of the source rect
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// calculate intersection of source rect with destination rect
|
||||
srcSubRect.IntersectRect(srcSubRect, dstInSrcRect);
|
||||
// this tile does not overlap the current destination tile
|
||||
if (srcSubRect.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// We now have the intersection of
|
||||
// the current source tile
|
||||
// and the desired source rectangle
|
||||
// and the destination tile
|
||||
// and the desired destination rectange
|
||||
// in destination space.
|
||||
// We need to transform this back into destination space, inverting the transform from (*)
|
||||
nsIntRect srcSubInDstRect(srcSubRect);
|
||||
srcSubInDstRect.MoveBy(-aSrcRect.TopLeft());
|
||||
srcSubInDstRect.ScaleRoundOut(blitScaleX, blitScaleY);
|
||||
srcSubInDstRect.MoveBy(aDstRect.TopLeft());
|
||||
|
||||
// we transform these rectangles to be relative to the current src and dst tiles, respectively
|
||||
nsIntSize srcSize = srcTextureRect.Size();
|
||||
nsIntSize dstSize = dstTextureRect.Size();
|
||||
srcSubRect.MoveBy(-srcTextureRect.x, -srcTextureRect.y);
|
||||
srcSubInDstRect.MoveBy(-dstTextureRect.x, -dstTextureRect.y);
|
||||
|
||||
float dx0 = 2.0f * float(srcSubInDstRect.x) / float(dstSize.width) - 1.0f;
|
||||
float dy0 = 2.0f * float(srcSubInDstRect.y) / float(dstSize.height) - 1.0f;
|
||||
float dx1 = 2.0f * float(srcSubInDstRect.x + srcSubInDstRect.width) / float(dstSize.width) - 1.0f;
|
||||
float dy1 = 2.0f * float(srcSubInDstRect.y + srcSubInDstRect.height) / float(dstSize.height) - 1.0f;
|
||||
PushViewportRect(nsIntRect(0, 0, dstSize.width, dstSize.height));
|
||||
|
||||
RectTriangles rects;
|
||||
|
||||
nsIntSize realTexSize = srcSize;
|
||||
if (!CanUploadNonPowerOfTwo()) {
|
||||
realTexSize = nsIntSize(NextPowerOfTwo(srcSize.width),
|
||||
NextPowerOfTwo(srcSize.height));
|
||||
}
|
||||
|
||||
if (aSrc->GetWrapMode() == LOCAL_GL_REPEAT) {
|
||||
rects.addRect(/* dest rectangle */
|
||||
dx0, dy0, dx1, dy1,
|
||||
/* tex coords */
|
||||
srcSubRect.x / float(realTexSize.width),
|
||||
srcSubRect.y / float(realTexSize.height),
|
||||
srcSubRect.XMost() / float(realTexSize.width),
|
||||
srcSubRect.YMost() / float(realTexSize.height));
|
||||
} else {
|
||||
DecomposeIntoNoRepeatTriangles(srcSubRect, realTexSize, rects);
|
||||
|
||||
// now put the coords into the d[xy]0 .. d[xy]1 coordinate space
|
||||
// from the 0..1 that it comes out of decompose
|
||||
RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
|
||||
|
||||
for (unsigned int i = 0; i < rects.elements(); ++i) {
|
||||
v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
|
||||
v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
|
||||
}
|
||||
}
|
||||
|
||||
TextureImage::ScopedBindTexture texBind(aSrc, LOCAL_GL_TEXTURE0);
|
||||
|
||||
fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
|
||||
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
|
||||
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
|
||||
|
||||
fEnableVertexAttribArray(0);
|
||||
fEnableVertexAttribArray(1);
|
||||
|
||||
fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
|
||||
|
||||
fDisableVertexAttribArray(0);
|
||||
fDisableVertexAttribArray(1);
|
||||
|
||||
PopViewportRect();
|
||||
} while (aSrc->NextTile());
|
||||
} while (aDst->NextTile());
|
||||
|
||||
fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
|
||||
fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, nullptr);
|
||||
|
||||
// unbind the previous texture from the framebuffer
|
||||
SetBlitFramebufferForDestTexture(0);
|
||||
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
|
||||
|
||||
fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
fEnable(LOCAL_GL_BLEND);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxImageFormat aFormat)
|
||||
{
|
||||
|
@ -2959,111 +2809,6 @@ GLContext::TexSubImage2DWithoutUnpackSubimage(GLenum target, GLint level,
|
|||
fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::UseBlitProgram()
|
||||
{
|
||||
if (mBlitProgram) {
|
||||
fUseProgram(mBlitProgram);
|
||||
return;
|
||||
}
|
||||
|
||||
mBlitProgram = fCreateProgram();
|
||||
|
||||
GLuint shaders[2];
|
||||
shaders[0] = fCreateShader(LOCAL_GL_VERTEX_SHADER);
|
||||
shaders[1] = fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
|
||||
|
||||
const char *blitVSSrc =
|
||||
"attribute vec2 aVertex;"
|
||||
"attribute vec2 aTexCoord;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" vTexCoord = aTexCoord;"
|
||||
" gl_Position = vec4(aVertex, 0.0, 1.0);"
|
||||
"}";
|
||||
const char *blitFSSrc = "#ifdef GL_ES\nprecision mediump float;\n#endif\n"
|
||||
"uniform sampler2D uSrcTexture;"
|
||||
"varying vec2 vTexCoord;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(uSrcTexture, vTexCoord);"
|
||||
"}";
|
||||
|
||||
fShaderSource(shaders[0], 1, (const GLchar**) &blitVSSrc, nullptr);
|
||||
fShaderSource(shaders[1], 1, (const GLchar**) &blitFSSrc, nullptr);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
GLint success, len = 0;
|
||||
|
||||
fCompileShader(shaders[i]);
|
||||
fGetShaderiv(shaders[i], LOCAL_GL_COMPILE_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader compilation failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
fGetShaderiv(shaders[i], LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
fGetShaderInfoLog(shaders[i], len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Shader %d compilation failed:\n%s\n", log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
fAttachShader(mBlitProgram, shaders[i]);
|
||||
fDeleteShader(shaders[i]);
|
||||
}
|
||||
|
||||
fBindAttribLocation(mBlitProgram, 0, "aVertex");
|
||||
fBindAttribLocation(mBlitProgram, 1, "aTexCoord");
|
||||
|
||||
fLinkProgram(mBlitProgram);
|
||||
|
||||
GLint success, len = 0;
|
||||
fGetProgramiv(mBlitProgram, LOCAL_GL_LINK_STATUS, &success);
|
||||
NS_ASSERTION(success, "Shader linking failed!");
|
||||
|
||||
if (!success) {
|
||||
nsAutoCString log;
|
||||
fGetProgramiv(mBlitProgram, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len);
|
||||
log.SetCapacity(len);
|
||||
fGetProgramInfoLog(mBlitProgram, len, (GLint*) &len, (char*) log.BeginWriting());
|
||||
log.SetLength(len);
|
||||
|
||||
printf_stderr("Program linking failed:\n%s\n", log.get());
|
||||
return;
|
||||
}
|
||||
|
||||
fUseProgram(mBlitProgram);
|
||||
fUniform1i(fGetUniformLocation(mBlitProgram, "uSrcTexture"), 0);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::SetBlitFramebufferForDestTexture(GLuint aTexture)
|
||||
{
|
||||
if (!mBlitFramebuffer) {
|
||||
fGenFramebuffers(1, &mBlitFramebuffer);
|
||||
}
|
||||
|
||||
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBlitFramebuffer);
|
||||
fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
|
||||
LOCAL_GL_COLOR_ATTACHMENT0,
|
||||
LOCAL_GL_TEXTURE_2D,
|
||||
aTexture,
|
||||
0);
|
||||
|
||||
GLenum result = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (aTexture && (result != LOCAL_GL_FRAMEBUFFER_COMPLETE)) {
|
||||
nsAutoCString msg;
|
||||
msg.Append("Framebuffer not complete -- error 0x");
|
||||
msg.AppendInt(result, 16);
|
||||
// Note: if you are hitting this, it is likely that
|
||||
// your texture is not texture complete -- that is, you
|
||||
// allocated a texture name, but didn't actually define its
|
||||
// size via a call to TexImage2D.
|
||||
NS_RUNTIMEABORT(msg.get());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
|
@ -3361,6 +3106,16 @@ GLContext::BlitHelper()
|
|||
return mBlitHelper;
|
||||
}
|
||||
|
||||
GLBlitTextureImageHelper*
|
||||
GLContext::BlitTextureImageHelper()
|
||||
{
|
||||
if (!mBlitTextureImageHelper) {
|
||||
mBlitTextureImageHelper = new GLBlitTextureImageHelper(this);
|
||||
}
|
||||
|
||||
return mBlitTextureImageHelper;
|
||||
}
|
||||
|
||||
bool
|
||||
DoesStringMatch(const char* aString, const char *aWantedString)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace mozilla {
|
|||
class GLScreenBuffer;
|
||||
class TextureGarbageBin;
|
||||
class GLBlitHelper;
|
||||
class GLBlitTextureImageHelper;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
|
@ -2762,34 +2763,6 @@ public:
|
|||
|
||||
TemporaryRef<gfx::SourceSurface> ReadPixelsToSourceSurface(const gfx::IntSize &aSize);
|
||||
|
||||
/**
|
||||
* Copy a rectangle from one TextureImage into another. The
|
||||
* source and destination are given in integer coordinates, and
|
||||
* will be converted to texture coordinates.
|
||||
*
|
||||
* For the source texture, the wrap modes DO apply -- it's valid
|
||||
* to use REPEAT or PAD and expect appropriate behaviour if the source
|
||||
* rectangle extends beyond its bounds.
|
||||
*
|
||||
* For the destination texture, the wrap modes DO NOT apply -- the
|
||||
* destination will be clipped by the bounds of the texture.
|
||||
*
|
||||
* Note: calling this function will cause the following OpenGL state
|
||||
* to be changed:
|
||||
*
|
||||
* - current program
|
||||
* - framebuffer binding
|
||||
* - viewport
|
||||
* - blend state (will be enabled at end)
|
||||
* - scissor state (will be enabled at end)
|
||||
* - vertex attrib 0 and 1 (pointer and enable state [enable state will be disabled at exit])
|
||||
* - array buffer binding (will be 0)
|
||||
* - active texture (will be 0)
|
||||
* - texture 0 binding
|
||||
*/
|
||||
void BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
|
||||
TextureImage *aDst, const nsIntRect& aDstRect);
|
||||
|
||||
/**
|
||||
* Creates a RGB/RGBA texture (or uses one provided) and uploads the surface
|
||||
* contents to it within aSrcRect.
|
||||
|
@ -2943,16 +2916,13 @@ protected:
|
|||
#endif
|
||||
bool mFlipped;
|
||||
|
||||
// lazy-initialized things
|
||||
GLuint mBlitProgram, mBlitFramebuffer;
|
||||
void UseBlitProgram();
|
||||
void SetBlitFramebufferForDestTexture(GLuint aTexture);
|
||||
|
||||
ScopedDeletePtr<GLBlitHelper> mBlitHelper;
|
||||
ScopedDeletePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
|
||||
|
||||
public:
|
||||
|
||||
GLBlitHelper* BlitHelper();
|
||||
GLBlitTextureImageHelper* BlitTextureImageHelper();
|
||||
|
||||
// Assumes shares are created by all sharing with the same global context.
|
||||
bool SharesWith(const GLContext* other) const {
|
||||
|
|
|
@ -29,6 +29,7 @@ EXPORTS += [
|
|||
'DecomposeIntoNoRepeatTriangles.h',
|
||||
'ForceDiscreteGPUHelperCGL.h',
|
||||
'GfxTexturesReporter.h',
|
||||
'GLBlitTextureImageHelper.h',
|
||||
'GLConsts.h',
|
||||
'GLContext.h',
|
||||
'GLContextProvider.h',
|
||||
|
@ -106,6 +107,7 @@ UNIFIED_SOURCES += [
|
|||
'DecomposeIntoNoRepeatTriangles.cpp',
|
||||
'GfxTexturesReporter.cpp',
|
||||
'GLBlitHelper.cpp',
|
||||
'GLBlitTextureImageHelper.cpp',
|
||||
'GLContext.cpp',
|
||||
'GLContextFeatures.cpp',
|
||||
'GLContextTypes.cpp',
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsPoint.h" // for nsIntPoint
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "GfxTexturesReporter.h" // for GfxTexturesReporter
|
||||
#include "GLBlitTextureImageHelper.h"
|
||||
#ifdef XP_MACOSX
|
||||
#include "SharedSurfaceIO.h"
|
||||
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
|
||||
|
@ -515,8 +516,8 @@ TextureImageDeprecatedTextureHostOGL::CopyTo(const nsIntRect& aSourceRect,
|
|||
aDest->AsSourceOGL()->AsTextureImageDeprecatedTextureHost();
|
||||
MOZ_ASSERT(dest, "Incompatible destination type!");
|
||||
|
||||
mGL->BlitTextureImage(mTexture, aSourceRect,
|
||||
dest->mTexture, aDestRect);
|
||||
mGL->BlitTextureImageHelper()->BlitTextureImage(mTexture, aSourceRect,
|
||||
dest->mTexture, aDestRect);
|
||||
dest->mTexture->MarkValid();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче