зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1750146 - Support SWGL x-flipped composites via linear path. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D136159
This commit is contained in:
Родитель
9b9347d03c
Коммит
eaf24f8a03
|
@ -248,7 +248,8 @@ static void linear_row_blit(uint16_t* dest, int span, const vec2_scalar& srcUV,
|
|||
template <bool COMPOSITE = false>
|
||||
static NO_INLINE void linear_blit(Texture& srctex, const IntRect& srcReq,
|
||||
Texture& dsttex, const IntRect& dstReq,
|
||||
bool invertY, const IntRect& clipRect) {
|
||||
bool invertX, bool invertY,
|
||||
const IntRect& clipRect) {
|
||||
assert(srctex.internal_format == GL_RGBA8 ||
|
||||
srctex.internal_format == GL_R8 || srctex.internal_format == GL_RG8);
|
||||
assert(!COMPOSITE || (srctex.internal_format == GL_RGBA8 &&
|
||||
|
@ -268,6 +269,11 @@ static NO_INLINE void linear_blit(Texture& srctex, const IntRect& srcReq,
|
|||
vec2_scalar srcUV(srcReq.x0, srcReq.y0);
|
||||
vec2_scalar srcDUV(float(srcReq.width()) / dstReq.width(),
|
||||
float(srcReq.height()) / dstReq.height());
|
||||
if (invertX) {
|
||||
// Advance to the end of the row and flip the step.
|
||||
srcUV.x += srcReq.width();
|
||||
srcDUV.x = -srcDUV.x;
|
||||
}
|
||||
// Inverted Y must step downward along source rows
|
||||
if (invertY) {
|
||||
srcUV.y += srcReq.height();
|
||||
|
@ -345,7 +351,7 @@ void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
|||
if (!srcReq.same_size(dstReq) && srctex.width >= 2 && filter == GL_LINEAR &&
|
||||
(srctex.internal_format == GL_RGBA8 || srctex.internal_format == GL_R8 ||
|
||||
srctex.internal_format == GL_RG8)) {
|
||||
linear_blit(srctex, srcReq, dsttex, dstReq, invertY, dstReq);
|
||||
linear_blit(srctex, srcReq, dsttex, dstReq, false, invertY, dstReq);
|
||||
} else {
|
||||
scale_blit(srctex, srcReq, dsttex, dstReq, invertY, clipRect);
|
||||
}
|
||||
|
@ -414,8 +420,9 @@ void* GetResourceBuffer(LockedTexture* resource, int32_t* width,
|
|||
void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
||||
GLint srcY, GLsizei srcWidth, GLsizei srcHeight, GLint dstX,
|
||||
GLint dstY, GLsizei dstWidth, GLsizei dstHeight,
|
||||
GLboolean opaque, GLboolean flip, GLenum filter, GLint clipX,
|
||||
GLint clipY, GLsizei clipWidth, GLsizei clipHeight) {
|
||||
GLboolean opaque, GLboolean flipX, GLboolean flipY,
|
||||
GLenum filter, GLint clipX, GLint clipY, GLsizei clipWidth,
|
||||
GLsizei clipHeight) {
|
||||
if (!lockedDst || !lockedSrc) {
|
||||
return;
|
||||
}
|
||||
|
@ -432,20 +439,25 @@ void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
|||
// as used for the sampling bounds.
|
||||
IntRect clipRect = {clipX - dstX, clipY - dstY, clipX - dstX + clipWidth,
|
||||
clipY - dstY + clipHeight};
|
||||
// Ensure we have rows of at least 2 pixels when using the linear filter to
|
||||
// avoid overreading the row. Force X flips onto the linear filter for now
|
||||
// until scale_blit supports it.
|
||||
bool useLinear =
|
||||
srctex.width >= 2 &&
|
||||
(flipX || (!srcReq.same_size(dstReq) && filter == GL_LINEAR));
|
||||
|
||||
if (opaque) {
|
||||
// Ensure we have rows of at least 2 pixels when using the linear filter
|
||||
// to avoid overreading the row.
|
||||
if (!srcReq.same_size(dstReq) && srctex.width >= 2 && filter == GL_LINEAR) {
|
||||
linear_blit<false>(srctex, srcReq, dsttex, dstReq, flip, clipRect);
|
||||
if (useLinear) {
|
||||
linear_blit<false>(srctex, srcReq, dsttex, dstReq, flipX, flipY,
|
||||
clipRect);
|
||||
} else {
|
||||
scale_blit<false>(srctex, srcReq, dsttex, dstReq, flip, clipRect);
|
||||
scale_blit<false>(srctex, srcReq, dsttex, dstReq, flipY, clipRect);
|
||||
}
|
||||
} else {
|
||||
if (!srcReq.same_size(dstReq) && srctex.width >= 2 && filter == GL_LINEAR) {
|
||||
linear_blit<true>(srctex, srcReq, dsttex, dstReq, flip, clipRect);
|
||||
if (useLinear) {
|
||||
linear_blit<true>(srctex, srcReq, dsttex, dstReq, flipX, flipY, clipRect);
|
||||
} else {
|
||||
scale_blit<true>(srctex, srcReq, dsttex, dstReq, flip, clipRect);
|
||||
scale_blit<true>(srctex, srcReq, dsttex, dstReq, flipY, clipRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -996,10 +1008,10 @@ static void linear_row_yuv(uint32_t* dest, int span, sampler2DRect samplerY,
|
|||
static void linear_convert_yuv(Texture& ytex, Texture& utex, Texture& vtex,
|
||||
const YUVMatrix& rgbFromYcbcr, int colorDepth,
|
||||
const IntRect& srcReq, Texture& dsttex,
|
||||
const IntRect& dstReq, bool invertY,
|
||||
const IntRect& clipRect) {
|
||||
const IntRect& dstReq, bool invertX,
|
||||
bool invertY, const IntRect& clipRect) {
|
||||
// Compute valid dest bounds
|
||||
IntRect dstBounds = dsttex.sample_bounds(dstReq, invertY);
|
||||
IntRect dstBounds = dsttex.sample_bounds(dstReq);
|
||||
dstBounds.intersect(clipRect);
|
||||
// Check if sampling bounds are empty
|
||||
if (dstBounds.is_empty()) {
|
||||
|
@ -1015,6 +1027,11 @@ static void linear_convert_yuv(Texture& ytex, Texture& utex, Texture& vtex,
|
|||
vec2_scalar srcUV(srcReq.x0, srcReq.y0);
|
||||
vec2_scalar srcDUV(float(srcReq.width()) / dstReq.width(),
|
||||
float(srcReq.height()) / dstReq.height());
|
||||
if (invertX) {
|
||||
// Advance to the end of the row and flip the step.
|
||||
srcUV.x += srcReq.width();
|
||||
srcDUV.x = -srcDUV.x;
|
||||
}
|
||||
// Inverted Y must step downward along source rows
|
||||
if (invertY) {
|
||||
srcUV.y += srcReq.height();
|
||||
|
@ -1182,8 +1199,8 @@ void CompositeYUV(LockedTexture* lockedDst, LockedTexture* lockedY,
|
|||
YUVRangedColorSpace colorSpace, GLuint colorDepth, GLint srcX,
|
||||
GLint srcY, GLsizei srcWidth, GLsizei srcHeight, GLint dstX,
|
||||
GLint dstY, GLsizei dstWidth, GLsizei dstHeight,
|
||||
GLboolean flip, GLint clipX, GLint clipY, GLsizei clipWidth,
|
||||
GLsizei clipHeight) {
|
||||
GLboolean flipX, GLboolean flipY, GLint clipX, GLint clipY,
|
||||
GLsizei clipWidth, GLsizei clipHeight) {
|
||||
if (!lockedDst || !lockedY || !lockedU || !lockedV) {
|
||||
return;
|
||||
}
|
||||
|
@ -1221,7 +1238,7 @@ void CompositeYUV(LockedTexture* lockedDst, LockedTexture* lockedY,
|
|||
// scaling. Further fast-paths for non-scaled video might be desirable in the
|
||||
// future.
|
||||
linear_convert_yuv(ytex, utex, vtex, rgbFromYcbcr, colorDepth, srcReq, dsttex,
|
||||
dstReq, flip, clipRect);
|
||||
dstReq, flipX, flipY, clipRect);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
@ -284,7 +284,8 @@ extern "C" {
|
|||
dst_width: GLsizei,
|
||||
dst_height: GLsizei,
|
||||
opaque: GLboolean,
|
||||
flip: GLboolean,
|
||||
flip_x: GLboolean,
|
||||
flip_y: GLboolean,
|
||||
filter: GLenum,
|
||||
clip_x: GLint,
|
||||
clip_y: GLint,
|
||||
|
@ -306,7 +307,8 @@ extern "C" {
|
|||
dst_y: GLint,
|
||||
dst_width: GLsizei,
|
||||
dst_height: GLsizei,
|
||||
flip: GLboolean,
|
||||
flip_x: GLboolean,
|
||||
flip_y: GLboolean,
|
||||
clip_x: GLint,
|
||||
clip_y: GLint,
|
||||
clip_width: GLsizei,
|
||||
|
@ -2322,7 +2324,8 @@ impl LockedResource {
|
|||
dst_width: GLsizei,
|
||||
dst_height: GLsizei,
|
||||
opaque: bool,
|
||||
flip: bool,
|
||||
flip_x: bool,
|
||||
flip_y: bool,
|
||||
filter: GLenum,
|
||||
clip_x: GLint,
|
||||
clip_y: GLint,
|
||||
|
@ -2342,7 +2345,8 @@ impl LockedResource {
|
|||
dst_width,
|
||||
dst_height,
|
||||
opaque as GLboolean,
|
||||
flip as GLboolean,
|
||||
flip_x as GLboolean,
|
||||
flip_y as GLboolean,
|
||||
filter,
|
||||
clip_x,
|
||||
clip_y,
|
||||
|
@ -2368,7 +2372,8 @@ impl LockedResource {
|
|||
dst_y: GLint,
|
||||
dst_width: GLsizei,
|
||||
dst_height: GLsizei,
|
||||
flip: bool,
|
||||
flip_x: bool,
|
||||
flip_y: bool,
|
||||
clip_x: GLint,
|
||||
clip_y: GLint,
|
||||
clip_width: GLsizei,
|
||||
|
@ -2390,7 +2395,8 @@ impl LockedResource {
|
|||
dst_y,
|
||||
dst_width,
|
||||
dst_height,
|
||||
flip as GLboolean,
|
||||
flip_x as GLboolean,
|
||||
flip_y as GLboolean,
|
||||
clip_x,
|
||||
clip_y,
|
||||
clip_width,
|
||||
|
|
|
@ -97,7 +97,7 @@ impl SwTile {
|
|||
surface: &SwSurface,
|
||||
transform: &CompositorSurfaceTransform,
|
||||
clip_rect: &DeviceIntRect,
|
||||
) -> Option<(DeviceIntRect, DeviceIntRect, bool)> {
|
||||
) -> Option<(DeviceIntRect, DeviceIntRect, bool, bool)> {
|
||||
// Offset the valid rect to the appropriate surface origin.
|
||||
let valid = self.local_bounds(surface);
|
||||
// The destination rect is the valid rect transformed and then clipped.
|
||||
|
@ -120,7 +120,7 @@ impl SwTile {
|
|||
dest_rect.size().try_cast::<i32>().is_none() {
|
||||
return None;
|
||||
}
|
||||
Some((src_rect.try_cast()?, dest_rect.try_cast()?, transform.m22 < 0.0))
|
||||
Some((src_rect.try_cast()?, dest_rect.try_cast()?, transform.m11 < 0.0, transform.m22 < 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,7 @@ struct SwCompositeJob {
|
|||
dst_rect: DeviceIntRect,
|
||||
clipped_dst: DeviceIntRect,
|
||||
opaque: bool,
|
||||
flip_x: bool,
|
||||
flip_y: bool,
|
||||
filter: ImageRendering,
|
||||
/// The total number of bands for this job
|
||||
|
@ -238,6 +239,7 @@ impl SwCompositeJob {
|
|||
self.dst_rect.width(),
|
||||
self.dst_rect.height(),
|
||||
self.opaque,
|
||||
self.flip_x,
|
||||
self.flip_y,
|
||||
image_rendering_to_gl_filter(self.filter),
|
||||
band_clip.min.x,
|
||||
|
@ -270,6 +272,7 @@ impl SwCompositeJob {
|
|||
self.dst_rect.min.y,
|
||||
self.dst_rect.width(),
|
||||
self.dst_rect.height(),
|
||||
self.flip_x,
|
||||
self.flip_y,
|
||||
band_clip.min.x,
|
||||
band_clip.min.y,
|
||||
|
@ -525,6 +528,7 @@ impl SwCompositeThread {
|
|||
dst_rect: DeviceIntRect,
|
||||
clip_rect: DeviceIntRect,
|
||||
opaque: bool,
|
||||
flip_x: bool,
|
||||
flip_y: bool,
|
||||
filter: ImageRendering,
|
||||
mut graph_node: SwCompositeGraphNodeRef,
|
||||
|
@ -549,6 +553,7 @@ impl SwCompositeThread {
|
|||
dst_rect,
|
||||
clipped_dst,
|
||||
opaque,
|
||||
flip_x,
|
||||
flip_y,
|
||||
filter,
|
||||
num_bands,
|
||||
|
@ -956,7 +961,7 @@ impl SwCompositor {
|
|||
job_queue: &mut SwCompositeJobQueue,
|
||||
) {
|
||||
if let Some(ref composite_thread) = self.composite_thread {
|
||||
if let Some((src_rect, dst_rect, flip_y)) = tile.composite_rects(surface, transform, clip_rect) {
|
||||
if let Some((src_rect, dst_rect, flip_x, flip_y)) = tile.composite_rects(surface, transform, clip_rect) {
|
||||
let source = if surface.external_image.is_some() {
|
||||
// If the surface has an attached external image, lock any textures supplied in the descriptor.
|
||||
match surface.composite_surface {
|
||||
|
@ -997,6 +1002,7 @@ impl SwCompositor {
|
|||
dst_rect,
|
||||
*clip_rect,
|
||||
surface.is_opaque,
|
||||
flip_x,
|
||||
flip_y,
|
||||
filter,
|
||||
tile.graph_node.clone(),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<div style="width: 100px; height: 100px;">
|
||||
<canvas id="c" width="100" height="100"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ctx = document.getElementById('c').getContext('2d', { alpha: false });
|
||||
ctx.fillStyle = 'red';
|
||||
ctx.fillRect(0, 0, 50, 100);
|
||||
ctx.fillStyle = 'green';
|
||||
ctx.fillRect(50, 0, 50, 100);
|
||||
</script>
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<div style="width: 100px; height: 100px; transform: scaleX(-1);">
|
||||
<canvas id="c" width="100" height="100"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ctx = document.getElementById('c').getContext('2d', { alpha: false });
|
||||
ctx.fillStyle = 'green';
|
||||
ctx.fillRect(0, 0, 50, 100);
|
||||
ctx.fillStyle = 'red';
|
||||
ctx.fillRect(50, 0, 50, 100);
|
||||
</script>
|
|
@ -2112,3 +2112,4 @@ skip-if(Android||!browserIsFission) fuzzy(255-255,171000-171000) HTTP == 1743533
|
|||
== 1743560-1.html 1743560-1-ref.html
|
||||
== 1743851-1.html 1743851-1-ref.html
|
||||
pref(image.downscale-during-decode.enabled,true) == 1744468-1.html 1744468-1-ref.html # do not increase fuzz without looking, the test should be smoothly downscaled, not pixelated
|
||||
== 1750146-1.html 1750146-1-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче