Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync changes from mozilla-central #3825

Merged
merged 2 commits into from Jan 8, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -27,6 +27,9 @@

#define NUM_QUERIES 2

#define USE_VIRTUAL_SURFACES
#define VIRTUAL_OFFSET 512 * 1024

enum SyncMode {
None = 0,
Swap = 1,
@@ -37,10 +40,12 @@ enum SyncMode {

// The OS compositor representation of a picture cache tile.
struct Tile {
#ifndef USE_VIRTUAL_SURFACES
// Represents the underlying DirectComposition surface texture that gets drawn into.
IDCompositionSurface *pSurface;
// Represents the node in the visual tree that defines the properties of this tile (clip, position etc).
IDCompositionVisual2 *pVisual;
#endif
};

struct TileKey {
@@ -66,6 +71,9 @@ struct Surface {
bool is_opaque;
std::unordered_map<TileKey, Tile, TileKeyHasher> tiles;
IDCompositionVisual2 *pVisual;
#ifdef USE_VIRTUAL_SURFACES
IDCompositionVirtualSurface *pVirtualSurface;
#endif
};

struct CachedFrameBuffer {
@@ -216,7 +224,8 @@ extern "C" {
name = L"example-compositor (Simple)";
}

window->hWnd = CreateWindow(
window->hWnd = CreateWindowEx(
WS_EX_NOREDIRECTIONBITMAP,
CLASS_NAME,
name,
WS_OVERLAPPEDWINDOW,
@@ -379,10 +388,12 @@ extern "C" {
for (auto surface_it=window->surfaces.begin() ; surface_it != window->surfaces.end() ; ++surface_it) {
Surface &surface = surface_it->second;

#ifndef USE_VIRTUAL_SURFACES
for (auto tile_it=surface.tiles.begin() ; tile_it != surface.tiles.end() ; ++tile_it) {
tile_it->second.pSurface->Release();
tile_it->second.pVisual->Release();
}
#endif

surface.pVisual->Release();
}
@@ -480,6 +491,23 @@ extern "C" {
HRESULT hr = window->pDCompDevice->CreateVisual(&surface.pVisual);
assert(SUCCEEDED(hr));

#ifdef USE_VIRTUAL_SURFACES
DXGI_ALPHA_MODE alpha_mode = surface.is_opaque ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;

hr = window->pDCompDevice->CreateVirtualSurface(
VIRTUAL_OFFSET * 2,
VIRTUAL_OFFSET * 2,
DXGI_FORMAT_B8G8R8A8_UNORM,
alpha_mode,
&surface.pVirtualSurface
);
assert(SUCCEEDED(hr));

// Bind the surface memory to this visual
hr = surface.pVisual->SetContent(surface.pVirtualSurface);
assert(SUCCEEDED(hr));
#endif

window->surfaces[id] = surface;
}

@@ -497,6 +525,7 @@ extern "C" {

Tile tile;

#ifndef USE_VIRTUAL_SURFACES
// Create the video memory surface.
DXGI_ALPHA_MODE alpha_mode = surface.is_opaque ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
HRESULT hr = window->pDCompDevice->CreateSurface(
@@ -527,6 +556,7 @@ extern "C" {
FALSE,
NULL
);
#endif

surface.tiles[key] = tile;
}
@@ -544,10 +574,12 @@ extern "C" {
assert(surface.tiles.count(key) == 1);
Tile &tile = surface.tiles[key];

#ifndef USE_VIRTUAL_SURFACES
surface.pVisual->RemoveVisual(tile.pVisual);

tile.pVisual->Release();
tile.pSurface->Release();
#endif

surface.tiles.erase(key);
}
@@ -561,11 +593,15 @@ extern "C" {

window->pRoot->RemoveVisual(surface.pVisual);

#ifdef USE_VIRTUAL_SURFACES
surface.pVirtualSurface->Release();
#else
// Release the video memory and visual in the tree
for (auto tile_it=surface.tiles.begin() ; tile_it != surface.tiles.end() ; ++tile_it) {
tile_it->second.pSurface->Release();
tile_it->second.pVisual->Release();
}
#endif

surface.pVisual->Release();
window->surfaces.erase(id);
@@ -591,9 +627,6 @@ extern "C" {
assert(surface.tiles.count(key) == 1);
Tile &tile = surface.tiles[key];

// Store the current surface for unbinding later
window->pCurrentSurface = tile.pSurface;

// Inform DC that we want to draw on this surface. DC uses texture
// atlases when the tiles are small. It returns an offset where the
// client code must draw into this surface when this happens.
@@ -605,17 +638,40 @@ extern "C" {
POINT offset;
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D *pTexture;
HRESULT hr = tile.pSurface->BeginDraw(
HRESULT hr;

// Store the current surface for unbinding later
#ifdef USE_VIRTUAL_SURFACES
LONG tile_offset_x = VIRTUAL_OFFSET + tile_x * surface.tile_width;
LONG tile_offset_y = VIRTUAL_OFFSET + tile_y * surface.tile_height;

update_rect.left += tile_offset_x;
update_rect.top += tile_offset_y;
update_rect.right += tile_offset_x;
update_rect.bottom += tile_offset_y;

hr = surface.pVirtualSurface->BeginDraw(
&update_rect,
__uuidof(ID3D11Texture2D),
(void **) &pTexture,
&offset
);
window->pCurrentSurface = surface.pVirtualSurface;
#else
hr = tile.pSurface->BeginDraw(
&update_rect,
__uuidof(ID3D11Texture2D),
(void **) &pTexture,
&offset
);
window->pCurrentSurface = tile.pSurface;
#endif

// DC includes the origin of the dirty / update rect in the draw offset,
// undo that here since WR expects it to be an absolute offset.
assert(SUCCEEDED(hr));
offset.x -= dirty_x0;
offset.y -= dirty_y0;
assert(SUCCEEDED(hr));
pTexture->GetDesc(&desc);
*x_offset = offset.x;
*y_offset = offset.y;
@@ -690,6 +746,10 @@ extern "C" {
// of the slice.
float offset_x = (float) (x + window->client_rect.left);
float offset_y = (float) (y + window->client_rect.top);
#ifdef USE_VIRTUAL_SURFACES
offset_x -= VIRTUAL_OFFSET;
offset_y -= VIRTUAL_OFFSET;
#endif
surface.pVisual->SetOffsetX(offset_x);
surface.pVisual->SetOffsetY(offset_y);

@@ -112,55 +112,66 @@ impl GlyphRasterizer {
let font_contexts = Arc::clone(&self.font_contexts);
let glyph_tx = self.glyph_tx.clone();

// spawn an async task to get off of the render backend thread as early as
// possible and in that task use rayon's fork join dispatch to rasterize the
// glyphs in the thread pool.
self.workers.spawn(move || {
let jobs = glyphs
.par_iter()
.map(|key: &GlyphKey| {
profile_scope!("glyph-raster");
let mut context = font_contexts.lock_current_context();
let mut job = GlyphRasterJob {
key: key.clone(),
result: context.rasterize_glyph(&font, key),
};

if let Ok(ref mut glyph) = job.result {
// Sanity check.
let bpp = 4; // We always render glyphs in 32 bits RGBA format.
assert_eq!(
glyph.bytes.len(),
bpp * (glyph.width * glyph.height) as usize
);

// a quick-and-dirty monochrome over
fn over(dst: u8, src: u8) -> u8 {
let a = src as u32;
let a = 256 - a;
let dst = ((dst as u32 * a) >> 8) as u8;
src + dst
}
fn process_glyph(key: &GlyphKey, font_contexts: &FontContexts, font: &FontInstance) -> GlyphRasterJob {
profile_scope!("glyph-raster");
let mut context = font_contexts.lock_current_context();
let mut job = GlyphRasterJob {
key: key.clone(),
result: context.rasterize_glyph(&font, key),
};

if let Ok(ref mut glyph) = job.result {
// Sanity check.
let bpp = 4; // We always render glyphs in 32 bits RGBA format.
assert_eq!(
glyph.bytes.len(),
bpp * (glyph.width * glyph.height) as usize
);

// a quick-and-dirty monochrome over
fn over(dst: u8, src: u8) -> u8 {
let a = src as u32;
let a = 256 - a;
let dst = ((dst as u32 * a) >> 8) as u8;
src + dst
}

if GLYPH_FLASHING.load(Ordering::Relaxed) {
let color = (random() & 0xff) as u8;
for i in &mut glyph.bytes {
*i = over(*i, color);
}
}
if GLYPH_FLASHING.load(Ordering::Relaxed) {
let color = (random() & 0xff) as u8;
for i in &mut glyph.bytes {
*i = over(*i, color);
}
}

assert_eq!((glyph.left.fract(), glyph.top.fract()), (0.0, 0.0));
assert_eq!((glyph.left.fract(), glyph.top.fract()), (0.0, 0.0));

// Check if the glyph has a bitmap that needs to be downscaled.
glyph.downscale_bitmap_if_required(&font);
}
// Check if the glyph has a bitmap that needs to be downscaled.
glyph.downscale_bitmap_if_required(&font);
}

job
})
.collect();
job
}

// if the number of glyphs is small, do it inline to avoid the threading overhead;
// send the result into glyph_tx so downstream code can't tell the difference.
if glyphs.len() < 8 {
let jobs = glyphs.iter()
.map(|key: &GlyphKey| process_glyph(key, &font_contexts, &font))
.collect();
glyph_tx.send(GlyphRasterJobs { font, jobs }).unwrap();
});
} else {
// spawn an async task to get off of the render backend thread as early as
// possible and in that task use rayon's fork join dispatch to rasterize the
// glyphs in the thread pool.
self.workers.spawn(move || {
let jobs = glyphs
.par_iter()
.map(|key: &GlyphKey| process_glyph(key, &font_contexts, &font))
.collect();

glyph_tx.send(GlyphRasterJobs { font, jobs }).unwrap();
});
}
}

pub fn resolve_glyphs(
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.