summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp')
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp274
1 files changed, 46 insertions, 228 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
index b181822ff..0a624dcb1 100755
--- a/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -30,7 +30,7 @@ gl::Error CheckCompileStatus(const rx::FunctionsGL *functions, GLuint shader)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to compile internal blit shader.");
}
- return gl::NoError();
+ return gl::Error(GL_NO_ERROR);
}
gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program)
@@ -43,7 +43,7 @@ gl::Error CheckLinkStatus(const rx::FunctionsGL *functions, GLuint program)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to link internal blit program.");
}
- return gl::NoError();
+ return gl::Error(GL_NO_ERROR);
}
} // anonymous namespace
@@ -58,9 +58,6 @@ BlitGL::BlitGL(const FunctionsGL *functions,
mWorkarounds(workarounds),
mStateManager(stateManager),
mBlitProgram(0),
- mSourceTextureLocation(-1),
- mScaleLocation(-1),
- mOffsetLocation(-1),
mScratchFBO(0),
mVAO(0)
{
@@ -133,7 +130,11 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source)
{
- ANGLE_TRY(initializeResources());
+ gl::Error error = initializeResources();
+ if (error.isError())
+ {
+ return error;
+ }
// Blit the framebuffer to the first scratch texture
const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
@@ -145,6 +146,7 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
const gl::InternalFormat &internalFormatInfo =
gl::GetInternalFormatInfo(copyTexImageFormat.internalFormat);
+ mStateManager->activeTexture(0);
mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, copyTexImageFormat.internalFormat, sourceArea.x,
sourceArea.y, sourceArea.width, sourceArea.height, 0);
@@ -169,6 +171,7 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
mScratchTextures[1], 0);
// Render to the destination texture, sampling from the scratch texture
+ mStateManager->useProgram(mBlitProgram);
mStateManager->setViewport(gl::Rectangle(0, 0, sourceArea.width, sourceArea.height));
mStateManager->setScissorTestEnabled(false);
mStateManager->setDepthRange(0.0f, 1.0f);
@@ -183,192 +186,16 @@ gl::Error BlitGL::copySubImageToLUMAWorkaroundTexture(GLuint texture,
mStateManager->setRasterizerDiscardEnabled(false);
mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
- setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- mStateManager->activeTexture(0);
- mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
-
- mStateManager->useProgram(mBlitProgram);
- mFunctions->uniform1i(mSourceTextureLocation, 0);
- mFunctions->uniform2f(mScaleLocation, 1.0, 1.0);
- mFunctions->uniform2f(mOffsetLocation, 0.0, 0.0);
-
mStateManager->bindVertexArray(mVAO, 0);
- mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
+ mFunctions->drawArrays(GL_TRIANGLES, 0, 6);
- // Copy the swizzled texture to the destination texture
+ // Finally, copy the swizzled texture to the destination texture
mStateManager->bindTexture(textureType, texture);
mFunctions->copyTexSubImage2D(target, static_cast<GLint>(level), destOffset.x, destOffset.y, 0,
0, sourceArea.width, sourceArea.height);
- // Finally orphan the scratch textures so they can be GCed by the driver.
- orphanScratchTextures();
-
- return gl::NoError();
-}
-
-gl::Error BlitGL::blitColorBufferWithShader(const gl::Framebuffer *source,
- const gl::Framebuffer *dest,
- const gl::Rectangle &sourceAreaIn,
- const gl::Rectangle &destAreaIn,
- GLenum filter)
-{
- ANGLE_TRY(initializeResources());
-
- // Normalize the destination area to have positive width and height because we will use
- // glViewport to set it, which doesn't allow negative width or height.
- gl::Rectangle sourceArea = sourceAreaIn;
- gl::Rectangle destArea = destAreaIn;
- if (destArea.width < 0)
- {
- destArea.x += destArea.width;
- destArea.width = -destArea.width;
- sourceArea.x += sourceArea.width;
- sourceArea.width = -sourceArea.width;
- }
- if (destArea.height < 0)
- {
- destArea.y += destArea.height;
- destArea.height = -destArea.height;
- sourceArea.y += sourceArea.height;
- sourceArea.height = -sourceArea.height;
- }
-
- const gl::FramebufferAttachment *readAttachment = source->getReadColorbuffer();
- ASSERT(readAttachment->getSamples() <= 1);
-
- // Compute the part of the source that will be sampled.
- gl::Rectangle inBoundsSource;
- {
- gl::Extents sourceSize = readAttachment->getSize();
- gl::Rectangle sourceBounds(0, 0, sourceSize.width, sourceSize.height);
- gl::ClipRectangle(sourceArea, sourceBounds, &inBoundsSource);
-
- // Note that inBoundsSource will have lost the orientation information.
- ASSERT(inBoundsSource.width >= 0 && inBoundsSource.height >= 0);
-
- // Early out when the sampled part is empty as the blit will be a noop,
- // and it prevents a division by zero in later computations.
- if (inBoundsSource.width == 0 || inBoundsSource.height == 0)
- {
- return gl::NoError();
- }
- }
-
- // The blit will be emulated by getting the source of the blit in a texture and sampling it
- // with CLAMP_TO_EDGE. The quad used to draw can trivially compute texture coordinates going
- // from (0, 0) to (1, 1). These texture coordinates will need to be transformed to make two
- // regions match:
- // - The region of the texture representing the source framebuffer region that will be sampled
- // - The region of the drawn quad that corresponds to non-clamped blit, this is the same as the
- // region of the source rectangle that is inside the source attachment.
- //
- // These two regions, T (texture) and D (dest) are defined by their offset in texcoord space
- // in (0, 1)^2 and their size in texcoord space in (-1, 1)^2. The size can be negative to
- // represent the orientation of the blit.
- //
- // Then if P is the quad texcoord, Q the texcoord inside T, and R the texture texcoord:
- // - Q = (P - D.offset) / D.size
- // - Q = (R - T.offset) / T.size
- // Hence R = (P - D.offset) / D.size * T.size - T.offset
- // = P * (T.size / D.size) + (T.offset - D.offset * T.size / D.size)
-
- GLuint textureId;
- gl::Vector2 TOffset;
- gl::Vector2 TSize;
-
- // TODO(cwallez) once texture dirty bits are landed, reuse attached texture instead of using
- // CopyTexImage2D
- {
- textureId = mScratchTextures[0];
- TOffset = gl::Vector2(0.0, 0.0);
- TSize = gl::Vector2(1.0, 1.0);
- if (sourceArea.width < 0)
- {
- TOffset.x = 1.0;
- TSize.x = -1.0;
- }
- if (sourceArea.height < 0)
- {
- TOffset.y = 1.0;
- TSize.y = -1.0;
- }
-
- GLenum format = readAttachment->getFormat().info->internalFormat;
- const FramebufferGL *sourceGL = GetImplAs<FramebufferGL>(source);
- mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceGL->getFramebufferID());
- mStateManager->bindTexture(GL_TEXTURE_2D, textureId);
-
- mFunctions->copyTexImage2D(GL_TEXTURE_2D, 0, format, inBoundsSource.x, inBoundsSource.y,
- inBoundsSource.width, inBoundsSource.height, 0);
- }
-
- // Compute normalized sampled draw quad region
- // It is the same as the region of the source rectangle that is in bounds.
- gl::Vector2 DOffset;
- gl::Vector2 DSize;
- {
- ASSERT(sourceArea.width != 0 && sourceArea.height != 0);
- gl::Rectangle orientedInBounds = inBoundsSource;
- if (sourceArea.width < 0)
- {
- orientedInBounds.x += orientedInBounds.width;
- orientedInBounds.width = -orientedInBounds.width;
- }
- if (sourceArea.height < 0)
- {
- orientedInBounds.y += orientedInBounds.height;
- orientedInBounds.height = -orientedInBounds.height;
- }
-
- DOffset =
- gl::Vector2(static_cast<float>(orientedInBounds.x - sourceArea.x) / sourceArea.width,
- static_cast<float>(orientedInBounds.y - sourceArea.y) / sourceArea.height);
- DSize = gl::Vector2(static_cast<float>(orientedInBounds.width) / sourceArea.width,
- static_cast<float>(orientedInBounds.height) / sourceArea.height);
- }
-
- ASSERT(DSize.x != 0.0 && DSize.y != 0.0);
- gl::Vector2 texCoordScale = gl::Vector2(TSize.x / DSize.x, TSize.y / DSize.y);
- gl::Vector2 texCoordOffset = gl::Vector2(TOffset.x - DOffset.x * texCoordScale.x,
- TOffset.y - DOffset.y * texCoordScale.y);
-
- // Reset all the state except scissor and viewport
- mStateManager->setDepthRange(0.0f, 1.0f);
- mStateManager->setBlendEnabled(false);
- mStateManager->setColorMask(true, true, true, true);
- mStateManager->setSampleAlphaToCoverageEnabled(false);
- mStateManager->setSampleCoverageEnabled(false);
- mStateManager->setDepthTestEnabled(false);
- mStateManager->setStencilTestEnabled(false);
- mStateManager->setCullFaceEnabled(false);
- mStateManager->setPolygonOffsetFillEnabled(false);
- mStateManager->setRasterizerDiscardEnabled(false);
-
- // Use the viewport to draw exactly to the destination rectangle
- mStateManager->setViewport(destArea);
-
- // Set uniforms
- setScratchTextureParameter(GL_TEXTURE_MIN_FILTER, filter);
- setScratchTextureParameter(GL_TEXTURE_MAG_FILTER, filter);
- setScratchTextureParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- setScratchTextureParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- mStateManager->activeTexture(0);
- mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[0]);
-
- mStateManager->useProgram(mBlitProgram);
- mFunctions->uniform1i(mSourceTextureLocation, 0);
- mFunctions->uniform2f(mScaleLocation, texCoordScale.x, texCoordScale.y);
- mFunctions->uniform2f(mOffsetLocation, texCoordOffset.x, texCoordOffset.y);
-
- const FramebufferGL *destGL = GetImplAs<FramebufferGL>(dest);
- mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, destGL->getFramebufferID());
-
- mStateManager->bindVertexArray(mVAO, 0);
- mFunctions->drawArrays(GL_TRIANGLES, 0, 3);
-
- return gl::NoError();
+ return gl::Error(GL_NO_ERROR);
}
gl::Error BlitGL::initializeResources()
@@ -378,38 +205,41 @@ gl::Error BlitGL::initializeResources()
mBlitProgram = mFunctions->createProgram();
// Compile the fragment shader
- // It uses a single, large triangle, to avoid arithmetic precision issues where fragments
- // with the same Y coordinate don't get exactly the same interpolated texcoord Y.
const char *vsSource =
"#version 150\n"
"out vec2 v_texcoord;\n"
- "uniform vec2 u_scale;\n"
- "uniform vec2 u_offset;\n"
"\n"
"void main()\n"
"{\n"
- " const vec2 quad_positions[3] = vec2[3]\n"
+ " const vec2 quad_positions[6] = vec2[6]\n"
" (\n"
- " vec2(-0.5f, 0.0f),\n"
- " vec2( 1.5f, 0.0f),\n"
- " vec2( 0.5f, 2.0f)\n"
+ " vec2(0.0f, 0.0f),\n"
+ " vec2(0.0f, 1.0f),\n"
+ " vec2(1.0f, 0.0f),\n"
+ "\n"
+ " vec2(0.0f, 1.0f),\n"
+ " vec2(1.0f, 0.0f),\n"
+ " vec2(1.0f, 1.0f)\n"
" );\n"
"\n"
" gl_Position = vec4((quad_positions[gl_VertexID] * 2.0) - 1.0, 0.0, 1.0);\n"
- " v_texcoord = quad_positions[gl_VertexID] * u_scale + u_offset;\n"
+ " v_texcoord = quad_positions[gl_VertexID];\n"
"}\n";
GLuint vs = mFunctions->createShader(GL_VERTEX_SHADER);
mFunctions->shaderSource(vs, 1, &vsSource, nullptr);
mFunctions->compileShader(vs);
- ANGLE_TRY(CheckCompileStatus(mFunctions, vs));
+ gl::Error error = CheckCompileStatus(mFunctions, vs);
mFunctions->attachShader(mBlitProgram, vs);
mFunctions->deleteShader(vs);
+ if (error.isError())
+ {
+ return error;
+ }
+
// Compile the vertex shader
- // It discards if the texcoord is outside (0, 1)^2 so the blitframebuffer workaround
- // doesn't write when the point sampled is outside of the source framebuffer.
const char *fsSource =
"#version 150\n"
"uniform sampler2D u_source_texture;\n"
@@ -418,28 +248,32 @@ gl::Error BlitGL::initializeResources()
"\n"
"void main()\n"
"{\n"
- " if (clamp(v_texcoord, vec2(0.0), vec2(1.0)) != v_texcoord)\n"
- " {\n"
- " discard;\n"
- " }\n"
" output_color = texture(u_source_texture, v_texcoord);\n"
"}\n";
GLuint fs = mFunctions->createShader(GL_FRAGMENT_SHADER);
mFunctions->shaderSource(fs, 1, &fsSource, nullptr);
mFunctions->compileShader(fs);
- ANGLE_TRY(CheckCompileStatus(mFunctions, fs));
+ error = CheckCompileStatus(mFunctions, fs);
mFunctions->attachShader(mBlitProgram, fs);
mFunctions->deleteShader(fs);
+ if (error.isError())
+ {
+ return error;
+ }
+
mFunctions->linkProgram(mBlitProgram);
- ANGLE_TRY(CheckLinkStatus(mFunctions, mBlitProgram));
+ error = CheckLinkStatus(mFunctions, mBlitProgram);
+ if (error.isError())
+ {
+ return error;
+ }
- mSourceTextureLocation = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture");
- mScaleLocation = mFunctions->getUniformLocation(mBlitProgram, "u_scale");
- mOffsetLocation = mFunctions->getUniformLocation(mBlitProgram, "u_offset");
+ GLuint textureUniform = mFunctions->getUniformLocation(mBlitProgram, "u_source_texture");
mStateManager->useProgram(mBlitProgram);
+ mFunctions->uniform1i(textureUniform, 0);
}
for (size_t i = 0; i < ArraySize(mScratchTextures); i++)
@@ -447,6 +281,11 @@ gl::Error BlitGL::initializeResources()
if (mScratchTextures[i] == 0)
{
mFunctions->genTextures(1, &mScratchTextures[i]);
+ mStateManager->bindTexture(GL_TEXTURE_2D, mScratchTextures[i]);
+
+ // Use nearest, non-mipmapped sampling with the scratch texture
+ mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ mFunctions->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
@@ -460,27 +299,6 @@ gl::Error BlitGL::initializeResources()
mFunctions->genVertexArrays(1, &mVAO);
}
- return gl::NoError();
+ return gl::Error(GL_NO_ERROR);
}
-
-void BlitGL::orphanScratchTextures()
-{
- for (auto texture : mScratchTextures)
- {
- mStateManager->bindTexture(GL_TEXTURE_2D, texture);
- mFunctions->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- nullptr);
- }
-}
-
-void BlitGL::setScratchTextureParameter(GLenum param, GLenum value)
-{
- for (auto texture : mScratchTextures)
- {
- mStateManager->bindTexture(GL_TEXTURE_2D, texture);
- mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
- mFunctions->texParameteri(GL_TEXTURE_2D, param, value);
- }
}
-
-} // namespace rx