aboutsummaryrefslogtreecommitdiffstats
path: root/third_party/webrender/example-compositor
diff options
context:
space:
mode:
authorMukilan Thiyagarajan <mukilan@igalia.com>2023-09-14 15:00:42 +0530
committerMukilan Thiyagarajan <mukilan@igalia.com>2023-09-14 15:00:42 +0530
commitc385b3c9737c17d59cb02e520c3b68b232cb6497 (patch)
treead598ffbbdfbcecd6a4cf458abe2afc702d92c27 /third_party/webrender/example-compositor
parent988e05a68b48c9e744bf49459faf41a1bd9b81d7 (diff)
downloadservo-revert-webrender.tar.gz
servo-revert-webrender.zip
Revert "Upgrade WebRender to e491e1ae637b2eed1e7195855d88357e5eb3ddf9 (#30323)"revert-webrender
This reverts commit a9d37cb85ac2c55fc630fccffe1ba60ff00f555b.
Diffstat (limited to 'third_party/webrender/example-compositor')
-rw-r--r--third_party/webrender/example-compositor/compositor-wayland/Cargo.toml11
-rw-r--r--third_party/webrender/example-compositor/compositor-wayland/build.rs63
-rw-r--r--third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp772
-rw-r--r--third_party/webrender/example-compositor/compositor-wayland/src/lib.rs269
-rw-r--r--third_party/webrender/example-compositor/compositor-windows/src/lib.cpp1246
-rw-r--r--third_party/webrender/example-compositor/compositor-windows/src/lib.rs6
-rw-r--r--third_party/webrender/example-compositor/compositor/Cargo.toml5
-rw-r--r--third_party/webrender/example-compositor/compositor/src/main.rs107
8 files changed, 696 insertions, 1783 deletions
diff --git a/third_party/webrender/example-compositor/compositor-wayland/Cargo.toml b/third_party/webrender/example-compositor/compositor-wayland/Cargo.toml
deleted file mode 100644
index 0f5bba73b5c..00000000000
--- a/third_party/webrender/example-compositor/compositor-wayland/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "compositor-wayland"
-version = "0.1.0"
-authors = ["Glenn Watson <gw@intuitionlibrary.com>",
- "Robert Mader <robert.mader@posteo.de>"]
-edition = "2018"
-license = "MPL-2.0"
-
-[build-dependencies]
-cc = "1.0"
-pkg-config = "^0.3.17"
diff --git a/third_party/webrender/example-compositor/compositor-wayland/build.rs b/third_party/webrender/example-compositor/compositor-wayland/build.rs
deleted file mode 100644
index ab418b94c79..00000000000
--- a/third_party/webrender/example-compositor/compositor-wayland/build.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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/. */
-
-use std::process::Command;
-use std::env;
-use std::fs;
-
-extern crate pkg_config;
-
-fn main() {
- let out_dir = env::var("OUT_DIR").unwrap();
-
- fs::create_dir_all(&format!("{}/include", out_dir)).unwrap();
- Command::new("wayland-scanner")
- .args(&["client-header", "/usr/share/wayland-protocols/stable/viewporter/viewporter.xml"])
- .arg(&format!("{}/include/viewporter-client-protocol.h", out_dir))
- .status().unwrap();
-
- Command::new("wayland-scanner")
- .args(&["public-code", "/usr/share/wayland-protocols/stable/viewporter/viewporter.xml"])
- .arg(&format!("{}/viewporter-protocol.c", out_dir))
- .status().unwrap();
-
- Command::new("wayland-scanner")
- .args(&["client-header", "/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml"])
- .arg(&format!("{}/include/xdg-shell-client-protocol.h", out_dir))
- .status().unwrap();
-
- Command::new("wayland-scanner")
- .args(&["public-code", "/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml"])
- .arg(&format!("{}/xdg-shell-protocol.c", out_dir))
- .status().unwrap();
-
- cc::Build::new()
- .include(&format!("{}/include", out_dir))
- .file("src/lib.cpp")
- .file(&format!("{}/viewporter-protocol.c", out_dir))
- .file(&format!("{}/xdg-shell-protocol.c", out_dir))
- .compile("wayland");
-
- println!("cargo:rustc-link-lib=dylib=stdc++");
-
- pkg_config::Config::new()
- .atleast_version("1")
- .probe("egl")
- .unwrap();
- pkg_config::Config::new()
- .atleast_version("1")
- .probe("gl")
- .unwrap();
- pkg_config::Config::new()
- .atleast_version("1")
- .probe("wayland-client")
- .unwrap();
- pkg_config::Config::new()
- .atleast_version("1")
- .probe("wayland-egl")
- .unwrap();
-
- println!("cargo:rerun-if-changed=src/lib.rs");
- println!("cargo:rerun-if-changed=src/lib.cpp");
-}
diff --git a/third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp b/third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp
deleted file mode 100644
index 5529c987a9e..00000000000
--- a/third_party/webrender/example-compositor/compositor-wayland/src/lib.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/* 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/. */
-
-#define UNICODE
-
-#include <algorithm>
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <map>
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <unordered_map>
-#include <vector>
-
-#include <wayland-client.h>
-#include <wayland-egl.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GL/gl.h>
-#include <GLES2/gl2.h>
-
-#include "viewporter-client-protocol.h"
-#include "xdg-shell-client-protocol.h"
-
-#define UNUSED(x) (void)(x)
-
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#define MAX(x, y) (((x) > (y)) ? (x) : (y))
-
-#define NUM_QUERIES 2
-
-#define VIRTUAL_OFFSET 512 * 1024
-
-enum SyncMode {
- None_ = 0,
- Swap = 1,
- Commit = 2,
- Flush = 3,
- Query = 4,
-};
-
-// The OS compositor representation of a picture cache tile.
-struct Tile {
- uint64_t surface_id;
- int x;
- int y;
-
- struct wl_surface* surface;
- struct wl_subsurface* subsurface;
- struct wp_viewport* viewport;
- struct wl_egl_window* egl_window;
- EGLSurface egl_surface;
- bool is_visible;
-
- std::vector<EGLint> damage_rects;
-};
-
-struct TileKey {
- int x;
- int y;
-
- TileKey(int ax, int ay) : x(ax), y(ay) {}
-};
-
-bool operator==(const TileKey& k0, const TileKey& k1) {
- return k0.x == k1.x && k0.y == k1.y;
-}
-
-struct TileKeyHasher {
- size_t operator()(const TileKey& key) const { return key.x ^ key.y; }
-};
-
-struct Surface {
- uint64_t id;
- int tile_width;
- int tile_height;
- bool is_opaque;
- std::unordered_map<TileKey, Tile*, TileKeyHasher> tiles;
-};
-
-struct WLDisplay {
- struct wl_display* display;
- struct wl_registry* registry;
- struct wl_compositor* compositor;
- struct wl_subcompositor* subcompositor;
- struct xdg_wm_base* wm_base;
- struct wl_seat* seat;
- struct wl_pointer* pointer;
- struct wl_touch* touch;
- struct wl_keyboard* keyboard;
- struct wl_shm* shm;
- struct wl_cursor_theme* cursor_theme;
- struct wl_cursor* default_cursor;
- struct wl_surface* cursor_surface;
- struct wp_viewporter* viewporter;
-
- PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC swap_buffers_with_damage;
-};
-
-struct WLGeometry {
- int width, height;
-};
-
-struct WLWindow {
- WLGeometry geometry;
- bool enable_compositor;
- SyncMode sync_mode;
- bool closed;
-
- WLDisplay* display;
- struct wl_surface* surface;
- struct xdg_surface* xdg_surface;
- struct xdg_toplevel* xdg_toplevel;
- struct wl_callback* callback;
- struct wp_viewport* viewport;
- bool wait_for_configure;
-
- struct wl_egl_window* egl_window;
- EGLSurface egl_surface;
-
- EGLDeviceEXT eglDevice;
- EGLDisplay eglDisplay;
- EGLContext eglContext;
- EGLConfig config;
-
- // Maintain list of layer state between frames to avoid visual tree rebuild.
- std::vector<uint64_t> currentLayers;
- std::vector<uint64_t> prevLayers;
-
- // Maps WR surface IDs to each OS surface
- std::unordered_map<uint64_t, Surface> surfaces;
- std::vector<Tile*> destroyedTiles;
- std::vector<Tile*> hiddenTiles;
-};
-
-extern "C" {
-
-static void init_wl_registry(WLWindow* window);
-static void init_xdg_window(WLWindow* window);
-
-WLWindow* com_wl_create_window(int width, int height, bool enable_compositor,
- SyncMode sync_mode) {
- WLDisplay* display = new WLDisplay;
- WLWindow* window = new WLWindow;
-
- window->display = display;
- window->geometry.width = width;
- window->geometry.height = height;
- window->enable_compositor = enable_compositor;
- window->sync_mode = sync_mode;
- window->closed = false;
-
- display->display = wl_display_connect(NULL);
- assert(display->display);
-
- init_wl_registry(window);
- if (enable_compositor && !display->viewporter) {
- fprintf(stderr, "Native compositor mode requires wp_viewporter support\n");
- window->closed = true;
- }
-
- window->eglDisplay =
- eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, display->display, NULL);
-
- eglInitialize(window->eglDisplay, nullptr, nullptr);
- eglBindAPI(EGL_OPENGL_API);
-
- EGLint num_configs = 0;
- EGLint cfg_attribs[] = {EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_BIT,
- EGL_RED_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_BLUE_SIZE,
- 8,
- EGL_ALPHA_SIZE,
- 8,
- EGL_DEPTH_SIZE,
- 24,
- EGL_NONE};
- EGLConfig configs[32];
-
- eglChooseConfig(window->eglDisplay, cfg_attribs, configs,
- sizeof(configs) / sizeof(EGLConfig), &num_configs);
- assert(num_configs > 0);
- window->config = configs[0];
-
- EGLint ctx_attribs[] = {EGL_CONTEXT_OPENGL_PROFILE_MASK,
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
- EGL_CONTEXT_MAJOR_VERSION,
- 3,
- EGL_CONTEXT_MINOR_VERSION,
- 2,
- EGL_NONE};
-
- // Create an EGL context that can be used for drawing
- window->eglContext = eglCreateContext(window->eglDisplay, window->config,
- EGL_NO_CONTEXT, ctx_attribs);
-
- window->surface = wl_compositor_create_surface(display->compositor);
- init_xdg_window(window);
-
- struct wl_region* region =
- wl_compositor_create_region(window->display->compositor);
- wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
- wl_surface_set_opaque_region(window->surface, region);
- wl_region_destroy(region);
-
- if (enable_compositor) {
- xdg_toplevel_set_title(window->xdg_toplevel,
- "example-compositor (Wayland)");
- } else {
- xdg_toplevel_set_title(window->xdg_toplevel, "example-compositor (Simple)");
- }
-
- window->wait_for_configure = true;
- wl_surface_commit(window->surface);
-
- EGLBoolean ok = eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE,
- EGL_NO_SURFACE, window->eglContext);
- assert(ok);
-
- display->swap_buffers_with_damage =
- (PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)eglGetProcAddress(
- "eglSwapBuffersWithDamageKHR");
-
- return window;
-}
-
-bool com_wl_tick(WLWindow* window) {
- if (window->wait_for_configure) {
- int ret = 0;
- while (window->wait_for_configure && !window->closed && ret != -1) {
- wl_display_dispatch(window->display->display);
- }
- } else {
- wl_display_dispatch_pending(window->display->display);
- }
-
- return !window->closed;
-}
-
-static void unmap_hidden_tiles(WLWindow* window) {
- for (Tile* tile : window->hiddenTiles) {
- if (tile->subsurface) {
- wl_subsurface_destroy(tile->subsurface);
- tile->subsurface = nullptr;
- }
- }
- window->hiddenTiles.clear();
-}
-
-static void clean_up_tiles(WLWindow* window) {
- for (Tile* tile : window->destroyedTiles) {
- eglDestroySurface(window->eglDisplay, tile->egl_surface);
- wl_egl_window_destroy(tile->egl_window);
- wp_viewport_destroy(tile->viewport);
- wl_surface_destroy(tile->surface);
- delete tile;
- }
- window->destroyedTiles.clear();
-}
-
-static void handle_callback(void* data, struct wl_callback* callback,
- uint32_t time) {
- WLWindow* window = (WLWindow*)data;
- UNUSED(time);
-
- assert(window->callback == callback);
-
- wl_callback_destroy(callback);
- window->callback = nullptr;
-}
-
-static const struct wl_callback_listener frame_listener = {handle_callback};
-
-void com_wl_swap_buffers(WLWindow* window) {
- if (window->enable_compositor) {
- for (auto surface_it = window->surfaces.begin();
- surface_it != window->surfaces.end(); ++surface_it) {
- Surface* surface = &surface_it->second;
-
- for (auto tile_it = surface->tiles.begin();
- tile_it != surface->tiles.end(); ++tile_it) {
- Tile* tile = tile_it->second;
-
- if (!tile->damage_rects.empty() && tile->is_visible) {
- eglMakeCurrent(window->eglDisplay, tile->egl_surface,
- tile->egl_surface, window->eglContext);
- eglSwapInterval(window->eglDisplay, 0);
-
- /* if (window->display->swap_buffers_with_damage) {
- window->display->swap_buffers_with_damage(
- window->eglDisplay, tile->egl_surface,
- tile->damage_rects.data(), tile->damage_rects.size() / 4);
- } else */
- eglSwapBuffers(window->eglDisplay, tile->egl_surface);
- tile->damage_rects.clear();
-
- eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
- window->eglContext);
- } else {
- wl_surface_commit(tile->surface);
- }
- }
- }
- wl_surface_commit(window->surface);
- unmap_hidden_tiles(window);
- clean_up_tiles(window);
-
- int ret = 0;
- switch (window->sync_mode) {
- case SyncMode::None_:
- wl_display_roundtrip(window->display->display);
- break;
- case SyncMode::Swap:
- window->callback = wl_surface_frame(window->surface);
- wl_callback_add_listener(window->callback, &frame_listener, window);
- wl_surface_commit(window->surface);
-
- while (window->callback && !window->closed && ret != -1) {
- ret = wl_display_dispatch(window->display->display);
- }
- break;
- default:
- assert(false);
- break;
- }
- } else {
- // If not using native mode, then do a normal EGL swap buffers.
- switch (window->sync_mode) {
- case SyncMode::None_:
- eglSwapInterval(window->eglDisplay, 0);
- break;
- case SyncMode::Swap:
- eglSwapInterval(window->eglDisplay, 1);
- break;
- default:
- assert(false);
- break;
- }
- eglSwapBuffers(window->eglDisplay, window->egl_surface);
- }
-}
-
-// Create a new native surface
-void com_wl_create_surface(WLWindow* window, uint64_t surface_id,
- int tile_width, int tile_height, bool is_opaque) {
- assert(window->surfaces.count(surface_id) == 0);
-
- Surface surface;
- surface.id = surface_id;
- surface.tile_width = tile_width;
- surface.tile_height = tile_height;
- surface.is_opaque = is_opaque;
-
- window->surfaces.emplace(surface_id, surface);
-}
-
-void com_wl_create_tile(WLWindow* window, uint64_t surface_id, int x, int y) {
- WLDisplay* display = window->display;
-
- assert(window->surfaces.count(surface_id) == 1);
- Surface* surface = &window->surfaces.at(surface_id);
-
- TileKey key(x, y);
- assert(surface->tiles.count(key) == 0);
-
- Tile* tile = new Tile;
- tile->surface_id = surface_id;
- tile->x = x;
- tile->y = y;
- tile->is_visible = false;
-
- tile->surface = wl_compositor_create_surface(display->compositor);
- tile->viewport =
- wp_viewporter_get_viewport(display->viewporter, tile->surface);
-
- if (surface->is_opaque) {
- struct wl_region* region =
- wl_compositor_create_region(window->display->compositor);
- wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
- wl_surface_set_opaque_region(tile->surface, region);
- wl_region_destroy(region);
- }
-
- tile->egl_window = wl_egl_window_create(tile->surface, surface->tile_width,
- surface->tile_height);
- tile->egl_surface = eglCreateWindowSurface(window->eglDisplay, window->config,
- tile->egl_window, NULL);
- assert(tile->egl_surface != EGL_NO_SURFACE);
-
- surface->tiles.emplace(key, tile);
-}
-
-static void show_tile(WLWindow* window, Tile* tile) {
- if (tile->is_visible) {
- assert(tile->subsurface);
- return;
- }
-
- tile->subsurface = wl_subcompositor_get_subsurface(
- window->display->subcompositor, tile->surface, window->surface);
-
- /* This is not comprehensive yet, see hide_tile() */
- Surface* surface = &window->surfaces.at(tile->surface_id);
- for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
- ++tile_it) {
- Tile* other_tile = tile_it->second;
-
- if (other_tile->is_visible) {
- wl_subsurface_place_above(tile->subsurface, other_tile->surface);
- }
- }
-
- tile->is_visible = true;
-}
-
-static void hide_tile(WLWindow* window, Tile* tile) {
- if (!tile->is_visible) {
- return;
- }
-
- /*
- * This is a workaround for missing API on the egl-wayland platform. We
- * likely want to replace it a solution that detaches the buffer from
- * the surface, which would require us to manage buffers manually.
- */
- wl_subsurface_set_position(tile->subsurface, window->geometry.width / 2,
- window->geometry.height / 2);
- wp_viewport_set_source(tile->viewport, wl_fixed_from_int(0),
- wl_fixed_from_int(0), wl_fixed_from_int(1),
- wl_fixed_from_int(1));
- wl_subsurface_place_below(tile->subsurface, window->surface);
- tile->is_visible = false;
- window->hiddenTiles.push_back(tile);
-}
-
-void com_wl_destroy_tile(WLWindow* window, uint64_t surface_id, int x, int y) {
- assert(window->surfaces.count(surface_id) == 1);
-
- Surface* surface = &window->surfaces.at(surface_id);
- TileKey key(x, y);
- assert(surface->tiles.count(key) == 1);
- Tile* tile = surface->tiles[key];
-
- hide_tile(window, tile);
- wl_surface_commit(tile->surface);
-
- window->destroyedTiles.push_back(tile);
- surface->tiles.erase(key);
-}
-
-void com_wl_destroy_surface(WLWindow* window, uint64_t surface_id) {
- assert(window->surfaces.count(surface_id) == 1);
-
- Surface* surface = &window->surfaces.at(surface_id);
- for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
- tile_it = surface->tiles.begin()) {
- Tile* tile = tile_it->second;
-
- com_wl_destroy_tile(window, surface_id, tile->x, tile->y);
- }
-
- window->surfaces.erase(surface_id);
-}
-
-void com_wl_destroy_window(WLWindow* window) {
- for (auto surface_it = window->surfaces.begin();
- surface_it != window->surfaces.end(); ++surface_it) {
- Surface& surface = surface_it->second;
-
- com_wl_destroy_surface(window, surface.id);
- }
-
- if (window->egl_surface != EGL_NO_SURFACE) {
- eglDestroySurface(window->eglDisplay, window->egl_surface);
- }
- eglDestroyContext(window->eglDisplay, window->eglContext);
- eglTerminate(window->eglDisplay);
-
- delete window;
-}
-
-// Bind a native surface to allow issuing GL commands to it
-GLuint com_wl_bind_surface(WLWindow* window, uint64_t surface_id, int tile_x,
- int tile_y, int* x_offset, int* y_offset,
- int dirty_x0, int dirty_y0, int dirty_width,
- int dirty_height) {
- *x_offset = 0;
- *y_offset = 0;
-
- assert(window->surfaces.count(surface_id) == 1);
- Surface* surface = &window->surfaces[surface_id];
-
- TileKey key(tile_x, tile_y);
- assert(surface->tiles.count(key) == 1);
- Tile* tile = surface->tiles[key];
-
- tile->damage_rects.push_back(dirty_x0);
- tile->damage_rects.push_back(dirty_y0);
- tile->damage_rects.push_back(dirty_width);
- tile->damage_rects.push_back(dirty_height);
-
- EGLBoolean ok = eglMakeCurrent(window->eglDisplay, tile->egl_surface,
- tile->egl_surface, window->eglContext);
- assert(ok);
-
- return 0;
-}
-
-// Unbind a currently bound native surface
-void com_wl_unbind_surface(WLWindow* window) {
- eglMakeCurrent(window->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
- window->eglContext);
-}
-
-void com_wl_begin_transaction(WLWindow*) {}
-
-// Add a native surface to the visual tree. Called per-frame to build the
-// composition.
-void com_wl_add_surface(WLWindow* window, uint64_t surface_id, int offset_x,
- int offset_y, int clip_x, int clip_y, int clip_w,
- int clip_h) {
- Surface* surface = &window->surfaces[surface_id];
- window->currentLayers.push_back(surface_id);
-
- for (auto tile_it = surface->tiles.begin(); tile_it != surface->tiles.end();
- ++tile_it) {
- Tile* tile = tile_it->second;
-
- int pos_x = MAX((tile->x * surface->tile_width) + offset_x, clip_x);
- int pos_y = MAX((tile->y * surface->tile_height) + offset_y, clip_y);
-
- float view_x = MAX((clip_x - offset_x) - tile->x * surface->tile_width, 0);
- float view_y = MAX((clip_y - offset_y) - tile->y * surface->tile_height, 0);
-
- float view_w = MIN(surface->tile_width - view_x, (clip_x + clip_w) - pos_x);
- float view_h =
- MIN(surface->tile_height - view_y, (clip_y + clip_h) - pos_y);
- view_w = MIN(window->geometry.width - pos_x, view_w);
- view_h = MIN(window->geometry.height - pos_y, view_h);
-
- if (view_w > 0 && view_h > 0) {
- show_tile(window, tile);
-
- wl_surface_set_buffer_transform(tile->surface,
- WL_OUTPUT_TRANSFORM_FLIPPED_180);
- wl_subsurface_set_position(tile->subsurface, pos_x, pos_y);
- wp_viewport_set_source(tile->viewport, wl_fixed_from_double(view_x),
- wl_fixed_from_double(view_y),
- wl_fixed_from_double(view_w),
- wl_fixed_from_double(view_h));
- } else {
- hide_tile(window, tile);
- }
- }
-}
-
-void com_wl_end_transaction(WLWindow* window) {
- bool same = window->prevLayers == window->currentLayers;
- if (!same) {
- struct wl_surface* prev_surface = window->surface;
-
- for (auto it = window->currentLayers.begin();
- it != window->currentLayers.end(); ++it) {
- Surface* surface = &window->surfaces[*it];
-
- struct wl_surface* next_surface = nullptr;
- for (auto tile_it = surface->tiles.begin();
- tile_it != surface->tiles.end(); ++tile_it) {
- Tile* tile = tile_it->second;
-
- if (tile->is_visible) {
- wl_subsurface_place_above(tile->subsurface, prev_surface);
-
- if (!next_surface) {
- next_surface = tile->surface;
- }
- }
- }
- prev_surface = next_surface;
- }
- }
-
- window->prevLayers.swap(window->currentLayers);
- window->currentLayers.clear();
-}
-
-void glInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
- const GLenum* attachments) {
- UNUSED(target);
- UNUSED(numAttachments);
- UNUSED(attachments);
-}
-
-// Get a pointer to an EGL symbol
-void* com_wl_get_proc_address(const char* name) {
- /* Disable glInvalidateFramebuffer for now as it triggers errors.
- * This is likely due to the egl-wayland platform, which we may want to
- * replace with a custom implementation in order to have more control
- * over the low-lever bits.
- */
- if (strcmp(name, "glInvalidateFramebuffer") == 0) {
- return (void*)glInvalidateFramebuffer;
- }
-
- return (void*)eglGetProcAddress(name);
-}
-
-void com_wl_deinit(WLWindow* window) { UNUSED(window); }
-
-static void handle_xdg_surface_configure(void* data,
- struct xdg_surface* surface,
- uint32_t serial) {
- WLWindow* window = (WLWindow*)data;
-
- xdg_surface_ack_configure(surface, serial);
-
- if (window->wait_for_configure) {
- if (window->enable_compositor) {
- int width = window->geometry.width;
- int height = window->geometry.height;
-
- window->egl_window = wl_egl_window_create(window->surface, 1, 1);
- window->egl_surface = eglCreateWindowSurface(
- window->eglDisplay, window->config, window->egl_window, NULL);
- assert(window->egl_surface != EGL_NO_SURFACE);
-
- EGLBoolean ok = eglMakeCurrent(window->eglDisplay, window->egl_surface,
- window->egl_surface, window->eglContext);
- assert(ok);
-
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- window->viewport = wp_viewporter_get_viewport(window->display->viewporter,
- window->surface);
- wp_viewport_set_destination(window->viewport, width, height);
-
- eglSwapBuffers(window->eglDisplay, window->egl_surface);
- } else {
- window->egl_window = wl_egl_window_create(
- window->surface, window->geometry.width, window->geometry.height);
- window->egl_surface = eglCreateWindowSurface(
- window->eglDisplay, window->config, window->egl_window, NULL);
- assert(window->egl_surface != EGL_NO_SURFACE);
-
- EGLBoolean ok = eglMakeCurrent(window->eglDisplay, window->egl_surface,
- window->egl_surface, window->eglContext);
- assert(ok);
- }
- }
-
- window->wait_for_configure = false;
-}
-
-static const struct xdg_surface_listener xdg_surface_listener = {
- handle_xdg_surface_configure};
-
-static void handle_xdg_toplevel_configure(void* data,
- struct xdg_toplevel* toplevel,
- int32_t width, int32_t height,
- struct wl_array* states) {
- WLWindow* window = (WLWindow*)data;
- UNUSED(toplevel);
- UNUSED(states);
-
- if (width > 0 && height > 0) {
- window->geometry.width = width;
- window->geometry.height = height;
-
- if (!window->wait_for_configure) {
- if (window->enable_compositor) {
- wp_viewport_set_destination(window->viewport, window->geometry.width,
- window->geometry.height);
- } else {
- wl_egl_window_resize(window->egl_window, window->geometry.width,
- window->geometry.height, 0, 0);
- }
- }
- }
-}
-
-static void handle_xdg_toplevel_close(void* data,
- struct xdg_toplevel* toplevel) {
- UNUSED(toplevel);
- WLWindow* window = (WLWindow*)data;
- window->closed = true;
-}
-
-static const struct xdg_toplevel_listener xdg_toplevel_listener = {
- handle_xdg_toplevel_configure,
- handle_xdg_toplevel_close,
-};
-
-static void xdg_wm_base_ping(void* data, struct xdg_wm_base* shell,
- uint32_t serial) {
- UNUSED(data);
- xdg_wm_base_pong(shell, serial);
-}
-
-static const struct xdg_wm_base_listener wm_base_listener = {
- xdg_wm_base_ping,
-};
-
-static void registry_handle_global(void* data, struct wl_registry* registry,
- uint32_t name, const char* interface,
- uint32_t version) {
- WLDisplay* d = (WLDisplay*)data;
-
- if (strcmp(interface, "wl_compositor") == 0) {
- d->compositor = (struct wl_compositor*)wl_registry_bind(
- registry, name, &wl_compositor_interface, MIN(version, 4));
- } else if (strcmp(interface, "wp_viewporter") == 0) {
- d->viewporter = (struct wp_viewporter*)wl_registry_bind(
- registry, name, &wp_viewporter_interface, 1);
- } else if (strcmp(interface, "xdg_wm_base") == 0) {
- d->wm_base = (struct xdg_wm_base*)wl_registry_bind(
- registry, name, &xdg_wm_base_interface, 1);
- xdg_wm_base_add_listener(d->wm_base, &wm_base_listener, NULL);
- } else if (strcmp(interface, "wl_subcompositor") == 0) {
- d->subcompositor = (struct wl_subcompositor*)wl_registry_bind(
- registry, name, &wl_subcompositor_interface, 1);
- }
-}
-
-static void registry_handle_global_remove(void* data,
- struct wl_registry* registry,
- uint32_t name) {
- UNUSED(data);
- UNUSED(registry);
- UNUSED(name);
-}
-
-static const struct wl_registry_listener registry_listener = {
- registry_handle_global, registry_handle_global_remove};
-
-static void init_wl_registry(WLWindow* window) {
- WLDisplay* display = window->display;
-
- display->registry = wl_display_get_registry(display->display);
- wl_registry_add_listener(display->registry, &registry_listener, display);
-
- wl_display_roundtrip(display->display);
-
- assert(display->compositor);
- assert(display->wm_base);
- assert(display->subcompositor);
-}
-
-static void init_xdg_window(WLWindow* window) {
- window->xdg_surface =
- xdg_wm_base_get_xdg_surface(window->display->wm_base, window->surface);
- assert(window->xdg_surface);
- xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window);
-
- window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface);
- xdg_toplevel_add_listener(window->xdg_toplevel, &xdg_toplevel_listener,
- window);
- assert(window->xdg_toplevel);
-}
-}
diff --git a/third_party/webrender/example-compositor/compositor-wayland/src/lib.rs b/third_party/webrender/example-compositor/compositor-wayland/src/lib.rs
deleted file mode 100644
index daddbb6495e..00000000000
--- a/third_party/webrender/example-compositor/compositor-wayland/src/lib.rs
+++ /dev/null
@@ -1,269 +0,0 @@
-/* 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/. */
-
-use std::os::raw::{c_void, c_char};
-
-/*
-
- This is a very simple (and unsafe!) rust wrapper for the Wayland / EGL
- implementation in lib.cpp.
-
- It just proxies the calls from the Compositor impl to the C99 code. This is very
- hacky and not suitable for production!
-
- */
-
-// Opaque wrapper for the Window type in lib.cpp
-#[repr(C)]
-pub struct Window {
- _unused: [u8; 0]
-}
-
-// C99 functions that do the compositor work
-extern {
- fn com_wl_create_window(
- width: i32,
- height: i32,
- enable_compositor: bool,
- sync_mode: i32,
- ) -> *mut Window;
- fn com_wl_destroy_window(window: *mut Window);
- fn com_wl_tick(window: *mut Window) -> bool;
- fn com_wl_get_proc_address(name: *const c_char) -> *const c_void;
- fn com_wl_swap_buffers(window: *mut Window);
-
- fn com_wl_create_surface(
- window: *mut Window,
- id: u64,
- tile_width: i32,
- tile_height: i32,
- is_opaque: bool,
- );
-
- fn com_wl_create_tile(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
- );
-
- fn com_wl_destroy_tile(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
- );
-
- fn com_wl_destroy_surface(
- window: *mut Window,
- id: u64,
- );
-
- fn com_wl_bind_surface(
- window: *mut Window,
- surface_id: u64,
- tile_x: i32,
- tile_y: i32,
- x_offset: &mut i32,
- y_offset: &mut i32,
- dirty_x0: i32,
- dirty_y0: i32,
- dirty_width: i32,
- dirty_height: i32,
- ) -> u32;
- fn com_wl_unbind_surface(window: *mut Window);
-
- fn com_wl_begin_transaction(window: *mut Window);
-
- fn com_wl_add_surface(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
- clip_x: i32,
- clip_y: i32,
- clip_w: i32,
- clip_h: i32,
- );
-
- fn com_wl_end_transaction(window: *mut Window);
-
- fn com_wl_deinit(window: *mut Window);
-}
-
-pub fn create_window(
- width: i32,
- height: i32,
- enable_compositor: bool,
- sync_mode: i32,
-) -> *mut Window {
- unsafe {
- com_wl_create_window(width, height, enable_compositor, sync_mode)
- }
-}
-
-pub fn destroy_window(window: *mut Window) {
- unsafe {
- com_wl_destroy_window(window);
- }
-}
-
-pub fn tick(window: *mut Window) -> bool {
- unsafe {
- com_wl_tick(window)
- }
-}
-
-pub fn get_proc_address(name: *const c_char) -> *const c_void {
- unsafe {
- com_wl_get_proc_address(name)
- }
-}
-
-pub fn create_surface(
- window: *mut Window,
- id: u64,
- tile_width: i32,
- tile_height: i32,
- is_opaque: bool,
-) {
- unsafe {
- com_wl_create_surface(
- window,
- id,
- tile_width,
- tile_height,
- is_opaque,
- )
- }
-}
-
-pub fn create_tile(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
-) {
- unsafe {
- com_wl_create_tile(
- window,
- id,
- x,
- y,
- )
- }
-}
-
-pub fn destroy_tile(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
-) {
- unsafe {
- com_wl_destroy_tile(
- window,
- id,
- x,
- y,
- )
- }
-}
-
-pub fn destroy_surface(
- window: *mut Window,
- id: u64,
-) {
- unsafe {
- com_wl_destroy_surface(
- window,
- id,
- )
- }
-}
-
-pub fn bind_surface(
- window: *mut Window,
- surface_id: u64,
- tile_x: i32,
- tile_y: i32,
- dirty_x0: i32,
- dirty_y0: i32,
- dirty_width: i32,
- dirty_height: i32,
-) -> (u32, i32, i32) {
- unsafe {
- let mut x_offset = 0;
- let mut y_offset = 0;
-
- let fbo_id = com_wl_bind_surface(
- window,
- surface_id,
- tile_x,
- tile_y,
- &mut x_offset,
- &mut y_offset,
- dirty_x0,
- dirty_y0,
- dirty_width,
- dirty_height,
- );
-
- (fbo_id, x_offset, y_offset)
- }
-}
-
-pub fn add_surface(
- window: *mut Window,
- id: u64,
- x: i32,
- y: i32,
- clip_x: i32,
- clip_y: i32,
- clip_w: i32,
- clip_h: i32,
-) {
- unsafe {
- com_wl_add_surface(
- window,
- id,
- x,
- y,
- clip_x,
- clip_y,
- clip_w,
- clip_h,
- )
- }
-}
-
-pub fn begin_transaction(window: *mut Window) {
- unsafe {
- com_wl_begin_transaction(window)
- }
-}
-
-pub fn unbind_surface(window: *mut Window) {
- unsafe {
- com_wl_unbind_surface(window)
- }
-}
-
-pub fn end_transaction(window: *mut Window) {
- unsafe {
- com_wl_end_transaction(window)
- }
-}
-
-pub fn swap_buffers(window: *mut Window) {
- unsafe {
- com_wl_swap_buffers(window);
- }
-}
-
-pub fn deinit(window: *mut Window) {
- unsafe {
- com_wl_deinit(window);
- }
-}
diff --git a/third_party/webrender/example-compositor/compositor-windows/src/lib.cpp b/third_party/webrender/example-compositor/compositor-windows/src/lib.cpp
index d39726ea0ab..e17f602a2ec 100644
--- a/third_party/webrender/example-compositor/compositor-windows/src/lib.cpp
+++ b/third_party/webrender/example-compositor/compositor-windows/src/lib.cpp
@@ -31,664 +31,772 @@
#define VIRTUAL_OFFSET 512 * 1024
enum SyncMode {
- None = 0,
- Swap = 1,
- Commit = 2,
- Flush = 3,
- Query = 4,
+ None = 0,
+ Swap = 1,
+ Commit = 2,
+ Flush = 3,
+ Query = 4,
};
// 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;
+ // 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 {
- int x;
- int y;
+ int x;
+ int y;
- TileKey(int ax, int ay) : x(ax), y(ay) {}
+ TileKey(int ax, int ay) : x(ax), y(ay) {}
};
-bool operator==(const TileKey& k0, const TileKey& k1) {
- return k0.x == k1.x && k0.y == k1.y;
+bool operator==(const TileKey &k0, const TileKey &k1) {
+ return k0.x == k1.x && k0.y == k1.y;
}
struct TileKeyHasher {
- size_t operator()(const TileKey& key) const { return key.x ^ key.y; }
+ size_t operator()(const TileKey &key) const {
+ return key.x ^ key.y;
+ }
};
struct Surface {
- int tile_width;
- int tile_height;
- bool is_opaque;
- std::unordered_map<TileKey, Tile, TileKeyHasher> tiles;
- IDCompositionVisual2* pVisual;
+ int tile_width;
+ int tile_height;
+ bool is_opaque;
+ std::unordered_map<TileKey, Tile, TileKeyHasher> tiles;
+ IDCompositionVisual2 *pVisual;
#ifdef USE_VIRTUAL_SURFACES
- IDCompositionVirtualSurface* pVirtualSurface;
+ IDCompositionVirtualSurface *pVirtualSurface;
#endif
};
struct CachedFrameBuffer {
- int width;
- int height;
- GLuint fboId;
- GLuint depthRboId;
+ int width;
+ int height;
+ GLuint fboId;
+ GLuint depthRboId;
};
struct Window {
- // Win32 window details
- HWND hWnd;
- HINSTANCE hInstance;
- bool enable_compositor;
- RECT client_rect;
- SyncMode sync_mode;
-
- // Main interfaces to D3D11 and DirectComposition
- ID3D11Device* pD3D11Device;
- IDCompositionDesktopDevice* pDCompDevice;
- IDCompositionTarget* pDCompTarget;
- IDXGIDevice* pDXGIDevice;
- ID3D11Query* pQueries[NUM_QUERIES];
- int current_query;
-
- // ANGLE interfaces that wrap the D3D device
- EGLDeviceEXT EGLDevice;
- EGLDisplay EGLDisplay;
- EGLContext EGLContext;
- EGLConfig config;
- // Framebuffer surface for debug mode when we are not using DC
- EGLSurface fb_surface;
-
- // The currently bound surface, valid during bind() and unbind()
- IDCompositionSurface* pCurrentSurface;
- EGLImage mEGLImage;
- GLuint mColorRBO;
-
- // The root of the DC visual tree. Nothing is drawn on this, but
- // all child tiles are parented to here.
- IDCompositionVisual2* pRoot;
- IDCompositionVisualDebug* pVisualDebug;
- std::vector<CachedFrameBuffer> mFrameBuffers;
-
- // Maintain list of layer state between frames to avoid visual tree rebuild.
- std::vector<uint64_t> mCurrentLayers;
- std::vector<uint64_t> mPrevLayers;
-
- // Maps WR surface IDs to each OS surface
- std::unordered_map<uint64_t, Surface> surfaces;
+ // Win32 window details
+ HWND hWnd;
+ HINSTANCE hInstance;
+ bool enable_compositor;
+ RECT client_rect;
+ SyncMode sync_mode;
+
+ // Main interfaces to D3D11 and DirectComposition
+ ID3D11Device *pD3D11Device;
+ IDCompositionDesktopDevice *pDCompDevice;
+ IDCompositionTarget *pDCompTarget;
+ IDXGIDevice *pDXGIDevice;
+ ID3D11Query *pQueries[NUM_QUERIES];
+ int current_query;
+
+ // ANGLE interfaces that wrap the D3D device
+ EGLDeviceEXT EGLDevice;
+ EGLDisplay EGLDisplay;
+ EGLContext EGLContext;
+ EGLConfig config;
+ // Framebuffer surface for debug mode when we are not using DC
+ EGLSurface fb_surface;
+
+ // The currently bound surface, valid during bind() and unbind()
+ IDCompositionSurface *pCurrentSurface;
+ EGLImage mEGLImage;
+ GLuint mColorRBO;
+
+ // The root of the DC visual tree. Nothing is drawn on this, but
+ // all child tiles are parented to here.
+ IDCompositionVisual2 *pRoot;
+ IDCompositionVisualDebug *pVisualDebug;
+ std::vector<CachedFrameBuffer> mFrameBuffers;
+
+ // Maintain list of layer state between frames to avoid visual tree rebuild.
+ std::vector<uint64_t> mCurrentLayers;
+ std::vector<uint64_t> mPrevLayers;
+
+ // Maps WR surface IDs to each OS surface
+ std::unordered_map<uint64_t, Surface> surfaces;
};
-static const wchar_t* CLASS_NAME = L"WR DirectComposite";
+static const wchar_t *CLASS_NAME = L"WR DirectComposite";
-static GLuint GetOrCreateFbo(Window* window, int aWidth, int aHeight) {
- GLuint fboId = 0;
+static GLuint GetOrCreateFbo(Window *window, int aWidth, int aHeight) {
+ GLuint fboId = 0;
- // Check if we have a cached FBO with matching dimensions
- for (auto it = window->mFrameBuffers.begin();
- it != window->mFrameBuffers.end(); ++it) {
- if (it->width == aWidth && it->height == aHeight) {
- fboId = it->fboId;
- break;
+ // Check if we have a cached FBO with matching dimensions
+ for (auto it = window->mFrameBuffers.begin(); it != window->mFrameBuffers.end(); ++it) {
+ if (it->width == aWidth && it->height == aHeight) {
+ fboId = it->fboId;
+ break;
+ }
}
- }
- // If not, create a new FBO with attached depth buffer
- if (fboId == 0) {
- // Create the depth buffer
- GLuint depthRboId;
- glGenRenderbuffers(1, &depthRboId);
- glBindRenderbuffer(GL_RENDERBUFFER, depthRboId);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, aWidth,
- aHeight);
-
- // Create the framebuffer and attach the depth buffer to it
- glGenFramebuffers(1, &fboId);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, depthRboId);
-
- // Store this in the cache for future calls.
- CachedFrameBuffer frame_buffer_info;
- frame_buffer_info.width = aWidth;
- frame_buffer_info.height = aHeight;
- frame_buffer_info.fboId = fboId;
- frame_buffer_info.depthRboId = depthRboId;
- window->mFrameBuffers.push_back(frame_buffer_info);
- }
-
- return fboId;
+ // If not, create a new FBO with attached depth buffer
+ if (fboId == 0) {
+ // Create the depth buffer
+ GLuint depthRboId;
+ glGenRenderbuffers(1, &depthRboId);
+ glBindRenderbuffer(GL_RENDERBUFFER, depthRboId);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
+ aWidth, aHeight);
+
+ // Create the framebuffer and attach the depth buffer to it
+ glGenFramebuffers(1, &fboId);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depthRboId);
+
+ // Store this in the cache for future calls.
+ CachedFrameBuffer frame_buffer_info;
+ frame_buffer_info.width = aWidth;
+ frame_buffer_info.height = aHeight;
+ frame_buffer_info.fboId = fboId;
+ frame_buffer_info.depthRboId = depthRboId;
+ window->mFrameBuffers.push_back(frame_buffer_info);
+ }
+
+ return fboId;
}
-static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
- LPARAM lParam) {
- switch (message) {
- case WM_DESTROY:
- PostQuitMessage(0);
- return 1;
- }
+static LRESULT CALLBACK WndProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+) {
+ switch (message) {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 1;
+ }
- return DefWindowProc(hwnd, message, wParam, lParam);
+ return DefWindowProc(hwnd, message, wParam, lParam);
}
extern "C" {
-Window* com_dc_create_window(int width, int height, bool enable_compositor,
- SyncMode sync_mode) {
- // Create a simple Win32 window
- Window* window = new Window;
- window->hInstance = GetModuleHandle(NULL);
- window->enable_compositor = enable_compositor;
- window->mEGLImage = EGL_NO_IMAGE;
- window->sync_mode = sync_mode;
-
- WNDCLASSEX wcex = {sizeof(WNDCLASSEX)};
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = window->hInstance;
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- ;
- wcex.lpszMenuName = nullptr;
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcex.lpszClassName = CLASS_NAME;
- RegisterClassEx(&wcex);
-
- int dpiX = 0;
- int dpiY = 0;
- HDC hdc = GetDC(NULL);
- if (hdc) {
- dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
- dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
- ReleaseDC(NULL, hdc);
- }
-
- RECT window_rect = {0, 0, width, height};
- AdjustWindowRect(&window_rect, WS_OVERLAPPEDWINDOW, FALSE);
- UINT window_width = static_cast<UINT>(
- ceil(float(window_rect.right - window_rect.left) * dpiX / 96.f));
- UINT window_height = static_cast<UINT>(
- ceil(float(window_rect.bottom - window_rect.top) * dpiY / 96.f));
-
- LPCWSTR name;
- DWORD style;
- if (enable_compositor) {
- name = L"example-compositor (DirectComposition)";
- style = WS_EX_NOREDIRECTIONBITMAP;
- } else {
- name = L"example-compositor (Simple)";
- style = 0;
- }
-
- window->hWnd =
- CreateWindowEx(style, CLASS_NAME, name, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, window_width, window_height,
- NULL, NULL, window->hInstance, NULL);
-
- ShowWindow(window->hWnd, SW_SHOWNORMAL);
- UpdateWindow(window->hWnd);
- GetClientRect(window->hWnd, &window->client_rect);
-
- // Create a D3D11 device
- D3D_FEATURE_LEVEL featureLevelSupported;
- HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL,
- D3D11_CREATE_DEVICE_BGRA_SUPPORT, NULL, 0,
- D3D11_SDK_VERSION, &window->pD3D11Device,
- &featureLevelSupported, nullptr);
- assert(SUCCEEDED(hr));
-
- D3D11_QUERY_DESC query_desc;
- memset(&query_desc, 0, sizeof(query_desc));
- query_desc.Query = D3D11_QUERY_EVENT;
- for (int i = 0; i < NUM_QUERIES; ++i) {
- hr = window->pD3D11Device->CreateQuery(&query_desc, &window->pQueries[i]);
- assert(SUCCEEDED(hr));
- }
- window->current_query = 0;
-
- hr = window->pD3D11Device->QueryInterface(&window->pDXGIDevice);
- assert(SUCCEEDED(hr));
-
- // Create a DirectComposition device
- hr = DCompositionCreateDevice2(window->pDXGIDevice,
- __uuidof(IDCompositionDesktopDevice),
- (void**)&window->pDCompDevice);
- assert(SUCCEEDED(hr));
-
- // Create a DirectComposition target for a Win32 window handle
- hr = window->pDCompDevice->CreateTargetForHwnd(window->hWnd, TRUE,
- &window->pDCompTarget);
- assert(SUCCEEDED(hr));
-
- // Create an ANGLE EGL device that wraps D3D11
- window->EGLDevice = eglCreateDeviceANGLE(EGL_D3D11_DEVICE_ANGLE,
- window->pD3D11Device, nullptr);
-
- EGLint display_attribs[] = {EGL_NONE};
-
- window->EGLDisplay = eglGetPlatformDisplayEXT(
- EGL_PLATFORM_DEVICE_EXT, window->EGLDevice, display_attribs);
-
- eglInitialize(window->EGLDisplay, nullptr, nullptr);
-
- EGLint num_configs = 0;
- EGLint cfg_attribs[] = {EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_BLUE_SIZE,
- 8,
- EGL_ALPHA_SIZE,
- 8,
- EGL_DEPTH_SIZE,
- 24,
- EGL_NONE};
- EGLConfig configs[32];
-
- eglChooseConfig(window->EGLDisplay, cfg_attribs, configs,
- sizeof(configs) / sizeof(EGLConfig), &num_configs);
- assert(num_configs > 0);
- window->config = configs[0];
-
- if (window->enable_compositor) {
- window->fb_surface = EGL_NO_SURFACE;
- } else {
- window->fb_surface = eglCreateWindowSurface(
- window->EGLDisplay, window->config, window->hWnd, NULL);
- assert(window->fb_surface != EGL_NO_SURFACE);
- }
-
- EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
-
- // Create an EGL context that can be used for drawing
- window->EGLContext = eglCreateContext(window->EGLDisplay, window->config,
- EGL_NO_CONTEXT, ctx_attribs);
-
- // Create the root of the DirectComposition visual tree
- hr = window->pDCompDevice->CreateVisual(&window->pRoot);
- assert(SUCCEEDED(hr));
- hr = window->pDCompTarget->SetRoot(window->pRoot);
- assert(SUCCEEDED(hr));
-
- hr = window->pRoot->QueryInterface(__uuidof(IDCompositionVisualDebug),
- (void**)&window->pVisualDebug);
- assert(SUCCEEDED(hr));
-
- // Uncomment this to see redraw regions during composite
- // window->pVisualDebug->EnableRedrawRegions();
-
- EGLBoolean ok = eglMakeCurrent(window->EGLDisplay, window->fb_surface,
- window->fb_surface, window->EGLContext);
- assert(ok);
-
- return window;
-}
+ Window *com_dc_create_window(int width, int height, bool enable_compositor, SyncMode sync_mode) {
+ // Create a simple Win32 window
+ Window *window = new Window;
+ window->hInstance = GetModuleHandle(NULL);
+ window->enable_compositor = enable_compositor;
+ window->mEGLImage = EGL_NO_IMAGE;
+ window->sync_mode = sync_mode;
+
+ WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = window->hInstance;
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);;
+ wcex.lpszMenuName = nullptr;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.lpszClassName = CLASS_NAME;
+ RegisterClassEx(&wcex);
+
+ int dpiX = 0;
+ int dpiY = 0;
+ HDC hdc = GetDC(NULL);
+ if (hdc) {
+ dpiX = GetDeviceCaps(hdc, LOGPIXELSX);
+ dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+ }
+
+ RECT window_rect = { 0, 0, width, height };
+ AdjustWindowRect(&window_rect, WS_OVERLAPPEDWINDOW, FALSE);
+ UINT window_width = static_cast<UINT>(ceil(float(window_rect.right - window_rect.left) * dpiX / 96.f));
+ UINT window_height = static_cast<UINT>(ceil(float(window_rect.bottom - window_rect.top) * dpiY / 96.f));
+
+ LPCWSTR name;
+ DWORD style;
+ if (enable_compositor) {
+ name = L"example-compositor (DirectComposition)";
+ style = WS_EX_NOREDIRECTIONBITMAP;
+ } else {
+ name = L"example-compositor (Simple)";
+ style = 0;
+ }
+
+ window->hWnd = CreateWindowEx(
+ style,
+ CLASS_NAME,
+ name,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ window_width,
+ window_height,
+ NULL,
+ NULL,
+ window->hInstance,
+ NULL
+ );
+
+ ShowWindow(window->hWnd, SW_SHOWNORMAL);
+ UpdateWindow(window->hWnd);
+ GetClientRect(window->hWnd, &window->client_rect);
+
+ // Create a D3D11 device
+ D3D_FEATURE_LEVEL featureLevelSupported;
+ HRESULT hr = D3D11CreateDevice(
+ nullptr,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+ NULL,
+ 0,
+ D3D11_SDK_VERSION,
+ &window->pD3D11Device,
+ &featureLevelSupported,
+ nullptr
+ );
+ assert(SUCCEEDED(hr));
+
+ D3D11_QUERY_DESC query_desc;
+ memset(&query_desc, 0, sizeof(query_desc));
+ query_desc.Query = D3D11_QUERY_EVENT;
+ for (int i=0 ; i < NUM_QUERIES ; ++i) {
+ hr = window->pD3D11Device->CreateQuery(&query_desc, &window->pQueries[i]);
+ assert(SUCCEEDED(hr));
+ }
+ window->current_query = 0;
+
+ hr = window->pD3D11Device->QueryInterface(&window->pDXGIDevice);
+ assert(SUCCEEDED(hr));
+
+ // Create a DirectComposition device
+ hr = DCompositionCreateDevice2(
+ window->pDXGIDevice,
+ __uuidof(IDCompositionDesktopDevice),
+ (void **) &window->pDCompDevice
+ );
+ assert(SUCCEEDED(hr));
+
+ // Create a DirectComposition target for a Win32 window handle
+ hr = window->pDCompDevice->CreateTargetForHwnd(
+ window->hWnd,
+ TRUE,
+ &window->pDCompTarget
+ );
+ assert(SUCCEEDED(hr));
+
+ // Create an ANGLE EGL device that wraps D3D11
+ window->EGLDevice = eglCreateDeviceANGLE(
+ EGL_D3D11_DEVICE_ANGLE,
+ window->pD3D11Device,
+ nullptr
+ );
+
+ EGLint display_attribs[] = {
+ EGL_NONE
+ };
+
+ window->EGLDisplay = eglGetPlatformDisplayEXT(
+ EGL_PLATFORM_DEVICE_EXT,
+ window->EGLDevice,
+ display_attribs
+ );
+
+ eglInitialize(
+ window->EGLDisplay,
+ nullptr,
+ nullptr
+ );
+
+ EGLint num_configs = 0;
+ EGLint cfg_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 24,
+ EGL_NONE
+ };
+ EGLConfig configs[32];
+
+ eglChooseConfig(
+ window->EGLDisplay,
+ cfg_attribs,
+ configs,
+ sizeof(configs) / sizeof(EGLConfig),
+ &num_configs
+ );
+ assert(num_configs > 0);
+ window->config = configs[0];
+
+ if (window->enable_compositor) {
+ window->fb_surface = EGL_NO_SURFACE;
+ } else {
+ window->fb_surface = eglCreateWindowSurface(
+ window->EGLDisplay,
+ window->config,
+ window->hWnd,
+ NULL
+ );
+ assert(window->fb_surface != EGL_NO_SURFACE);
+ }
+
+ EGLint ctx_attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_NONE
+ };
+
+ // Create an EGL context that can be used for drawing
+ window->EGLContext = eglCreateContext(
+ window->EGLDisplay,
+ window->config,
+ EGL_NO_CONTEXT,
+ ctx_attribs
+ );
+
+ // Create the root of the DirectComposition visual tree
+ hr = window->pDCompDevice->CreateVisual(&window->pRoot);
+ assert(SUCCEEDED(hr));
+ hr = window->pDCompTarget->SetRoot(window->pRoot);
+ assert(SUCCEEDED(hr));
+
+ hr = window->pRoot->QueryInterface(
+ __uuidof(IDCompositionVisualDebug),
+ (void **) &window->pVisualDebug
+ );
+ assert(SUCCEEDED(hr));
+
+ // Uncomment this to see redraw regions during composite
+ // window->pVisualDebug->EnableRedrawRegions();
+
+ EGLBoolean ok = eglMakeCurrent(
+ window->EGLDisplay,
+ window->fb_surface,
+ window->fb_surface,
+ window->EGLContext
+ );
+ assert(ok);
+
+ return window;
+ }
-void com_dc_destroy_window(Window* window) {
- for (auto surface_it = window->surfaces.begin();
- surface_it != window->surfaces.end(); ++surface_it) {
- Surface& surface = surface_it->second;
+ void com_dc_destroy_window(Window *window) {
+ 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();
- }
+ 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();
- }
-
- if (window->fb_surface != EGL_NO_SURFACE) {
- eglDestroySurface(window->EGLDisplay, window->fb_surface);
- }
- eglDestroyContext(window->EGLDisplay, window->EGLContext);
- eglTerminate(window->EGLDisplay);
- eglReleaseDeviceANGLE(window->EGLDevice);
-
- for (int i = 0; i < NUM_QUERIES; ++i) {
- window->pQueries[i]->Release();
- }
- window->pRoot->Release();
- window->pVisualDebug->Release();
- window->pD3D11Device->Release();
- window->pDXGIDevice->Release();
- window->pDCompDevice->Release();
- window->pDCompTarget->Release();
-
- CloseWindow(window->hWnd);
- UnregisterClass(CLASS_NAME, window->hInstance);
-
- delete window;
-}
-
-bool com_dc_tick(Window*) {
- // Check and dispatch the windows event loop
- MSG msg;
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- if (msg.message == WM_QUIT) {
- return false;
+ surface.pVisual->Release();
+ }
+
+ if (window->fb_surface != EGL_NO_SURFACE) {
+ eglDestroySurface(window->EGLDisplay, window->fb_surface);
+ }
+ eglDestroyContext(window->EGLDisplay, window->EGLContext);
+ eglTerminate(window->EGLDisplay);
+ eglReleaseDeviceANGLE(window->EGLDevice);
+
+ for (int i=0 ; i < NUM_QUERIES ; ++i) {
+ window->pQueries[i]->Release();
+ }
+ window->pRoot->Release();
+ window->pVisualDebug->Release();
+ window->pD3D11Device->Release();
+ window->pDXGIDevice->Release();
+ window->pDCompDevice->Release();
+ window->pDCompTarget->Release();
+
+ CloseWindow(window->hWnd);
+ UnregisterClass(CLASS_NAME, window->hInstance);
+
+ delete window;
}
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
+ bool com_dc_tick(Window *) {
+ // Check and dispatch the windows event loop
+ MSG msg;
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ if (msg.message == WM_QUIT) {
+ return false;
+ }
- return true;
-}
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
-void com_dc_swap_buffers(Window* window) {
- // If not using DC mode, then do a normal EGL swap buffers.
- if (window->fb_surface != EGL_NO_SURFACE) {
- switch (window->sync_mode) {
- case SyncMode::None:
- eglSwapInterval(window->EGLDisplay, 0);
- break;
- case SyncMode::Swap:
- eglSwapInterval(window->EGLDisplay, 1);
- break;
- default:
- assert(false); // unexpected vsync mode for simple compositor.
- break;
+ return true;
}
- eglSwapBuffers(window->EGLDisplay, window->fb_surface);
- } else {
- switch (window->sync_mode) {
- case SyncMode::None:
- break;
- case SyncMode::Commit:
- window->pDCompDevice->WaitForCommitCompletion();
- break;
- case SyncMode::Flush:
- DwmFlush();
- break;
- case SyncMode::Query:
- // todo!!!!
- break;
- default:
- assert(false); // unexpected vsync mode for native compositor
- break;
+ void com_dc_swap_buffers(Window *window) {
+ // If not using DC mode, then do a normal EGL swap buffers.
+ if (window->fb_surface != EGL_NO_SURFACE) {
+ switch (window->sync_mode) {
+ case SyncMode::None:
+ eglSwapInterval(window->EGLDisplay, 0);
+ break;
+ case SyncMode::Swap:
+ eglSwapInterval(window->EGLDisplay, 1);
+ break;
+ default:
+ assert(false); // unexpected vsync mode for simple compositor.
+ break;
+ }
+
+ eglSwapBuffers(window->EGLDisplay, window->fb_surface);
+ } else {
+ switch (window->sync_mode) {
+ case SyncMode::None:
+ break;
+ case SyncMode::Commit:
+ window->pDCompDevice->WaitForCommitCompletion();
+ break;
+ case SyncMode::Flush:
+ DwmFlush();
+ break;
+ case SyncMode::Query:
+ // todo!!!!
+ break;
+ default:
+ assert(false); // unexpected vsync mode for native compositor
+ break;
+ }
+ }
}
- }
-}
-
-// Create a new DC surface
-void com_dc_create_surface(Window* window, uint64_t id, int tile_width,
- int tile_height, bool is_opaque) {
- assert(window->surfaces.count(id) == 0);
- Surface surface;
- surface.tile_width = tile_width;
- surface.tile_height = tile_height;
- surface.is_opaque = is_opaque;
-
- // Create the visual node in the DC tree that stores properties
- HRESULT hr = window->pDCompDevice->CreateVisual(&surface.pVisual);
- assert(SUCCEEDED(hr));
+ // Create a new DC surface
+ void com_dc_create_surface(
+ Window *window,
+ uint64_t id,
+ int tile_width,
+ int tile_height,
+ bool is_opaque
+ ) {
+ assert(window->surfaces.count(id) == 0);
+
+ Surface surface;
+ surface.tile_width = tile_width;
+ surface.tile_height = tile_height;
+ surface.is_opaque = is_opaque;
+
+ // Create the visual node in the DC tree that stores properties
+ 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));
+ 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;
-}
+ window->surfaces[id] = surface;
+ }
-void com_dc_create_tile(Window* window, uint64_t id, int x, int y) {
- assert(window->surfaces.count(id) == 1);
- Surface& surface = window->surfaces[id];
+ void com_dc_create_tile(
+ Window *window,
+ uint64_t id,
+ int x,
+ int y
+ ) {
+ assert(window->surfaces.count(id) == 1);
+ Surface &surface = window->surfaces[id];
- TileKey key(x, y);
- assert(surface.tiles.count(key) == 0);
+ TileKey key(x, y);
+ assert(surface.tiles.count(key) == 0);
- Tile tile;
+ 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(
- surface.tile_width, surface.tile_height, DXGI_FORMAT_B8G8R8A8_UNORM,
- alpha_mode, &tile.pSurface);
- assert(SUCCEEDED(hr));
-
- // Create the visual node in the DC tree that stores properties
- hr = window->pDCompDevice->CreateVisual(&tile.pVisual);
- assert(SUCCEEDED(hr));
-
- // Bind the surface memory to this visual
- hr = tile.pVisual->SetContent(tile.pSurface);
- assert(SUCCEEDED(hr));
-
- // Place the visual in local-space of this surface
- float offset_x = (float)(x * surface.tile_width);
- float offset_y = (float)(y * surface.tile_height);
- tile.pVisual->SetOffsetX(offset_x);
- tile.pVisual->SetOffsetY(offset_y);
-
- surface.pVisual->AddVisual(tile.pVisual, FALSE, NULL);
+ // 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(
+ surface.tile_width,
+ surface.tile_height,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ alpha_mode,
+ &tile.pSurface
+ );
+ assert(SUCCEEDED(hr));
+
+ // Create the visual node in the DC tree that stores properties
+ hr = window->pDCompDevice->CreateVisual(&tile.pVisual);
+ assert(SUCCEEDED(hr));
+
+ // Bind the surface memory to this visual
+ hr = tile.pVisual->SetContent(tile.pSurface);
+ assert(SUCCEEDED(hr));
+
+ // Place the visual in local-space of this surface
+ float offset_x = (float) (x * surface.tile_width);
+ float offset_y = (float) (y * surface.tile_height);
+ tile.pVisual->SetOffsetX(offset_x);
+ tile.pVisual->SetOffsetY(offset_y);
+
+ surface.pVisual->AddVisual(
+ tile.pVisual,
+ FALSE,
+ NULL
+ );
#endif
- surface.tiles[key] = tile;
-}
+ surface.tiles[key] = tile;
+ }
-void com_dc_destroy_tile(Window* window, uint64_t id, int x, int y) {
- assert(window->surfaces.count(id) == 1);
- Surface& surface = window->surfaces[id];
+ void com_dc_destroy_tile(
+ Window *window,
+ uint64_t id,
+ int x,
+ int y
+ ) {
+ assert(window->surfaces.count(id) == 1);
+ Surface &surface = window->surfaces[id];
- TileKey key(x, y);
- assert(surface.tiles.count(key) == 1);
- Tile& tile = surface.tiles[key];
+ TileKey key(x, y);
+ assert(surface.tiles.count(key) == 1);
+ Tile &tile = surface.tiles[key];
#ifndef USE_VIRTUAL_SURFACES
- surface.pVisual->RemoveVisual(tile.pVisual);
+ surface.pVisual->RemoveVisual(tile.pVisual);
- tile.pVisual->Release();
- tile.pSurface->Release();
+ tile.pVisual->Release();
+ tile.pSurface->Release();
#endif
- surface.tiles.erase(key);
-}
+ surface.tiles.erase(key);
+ }
-void com_dc_destroy_surface(Window* window, uint64_t id) {
- assert(window->surfaces.count(id) == 1);
- Surface& surface = window->surfaces[id];
+ void com_dc_destroy_surface(
+ Window *window,
+ uint64_t id
+ ) {
+ assert(window->surfaces.count(id) == 1);
+ Surface &surface = window->surfaces[id];
- window->pRoot->RemoveVisual(surface.pVisual);
+ window->pRoot->RemoveVisual(surface.pVisual);
#ifdef USE_VIRTUAL_SURFACES
- surface.pVirtualSurface->Release();
+ 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();
- }
+ // 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);
-}
+ surface.pVisual->Release();
+ window->surfaces.erase(id);
+ }
-// Bind a DC surface to allow issuing GL commands to it
-GLuint com_dc_bind_surface(Window* window, uint64_t surface_id, int tile_x,
- int tile_y, int* x_offset, int* y_offset,
- int dirty_x0, int dirty_y0, int dirty_width,
- int dirty_height) {
- assert(window->surfaces.count(surface_id) == 1);
- Surface& surface = window->surfaces[surface_id];
-
- TileKey key(tile_x, tile_y);
- assert(surface.tiles.count(key) == 1);
- Tile& tile = surface.tiles[key];
-
- // 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.
- RECT update_rect;
- update_rect.left = dirty_x0;
- update_rect.top = dirty_y0;
- update_rect.right = dirty_x0 + dirty_width;
- update_rect.bottom = dirty_y0 + dirty_height;
- POINT offset;
- D3D11_TEXTURE2D_DESC desc;
- ID3D11Texture2D* pTexture;
- HRESULT hr;
-
- // Store the current surface for unbinding later
+ // Bind a DC surface to allow issuing GL commands to it
+ GLuint com_dc_bind_surface(
+ Window *window,
+ uint64_t surface_id,
+ int tile_x,
+ int tile_y,
+ int *x_offset,
+ int *y_offset,
+ int dirty_x0,
+ int dirty_y0,
+ int dirty_width,
+ int dirty_height
+ ) {
+ assert(window->surfaces.count(surface_id) == 1);
+ Surface &surface = window->surfaces[surface_id];
+
+ TileKey key(tile_x, tile_y);
+ assert(surface.tiles.count(key) == 1);
+ Tile &tile = surface.tiles[key];
+
+ // 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.
+ RECT update_rect;
+ update_rect.left = dirty_x0;
+ update_rect.top = dirty_y0;
+ update_rect.right = dirty_x0 + dirty_width;
+ update_rect.bottom = dirty_y0 + dirty_height;
+ POINT offset;
+ D3D11_TEXTURE2D_DESC desc;
+ ID3D11Texture2D *pTexture;
+ 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;
+ 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;
+ 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;
- pTexture->GetDesc(&desc);
- *x_offset = offset.x;
- *y_offset = offset.y;
-
- // Construct an EGLImage wrapper around the D3D texture for ANGLE.
- const EGLAttrib attribs[] = {EGL_NONE};
- window->mEGLImage = eglCreateImage(
- window->EGLDisplay, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
- static_cast<EGLClientBuffer>(pTexture), attribs);
-
- // Get the current FBO and RBO id, so we can restore them later
- GLint currentFboId, currentRboId;
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFboId);
- glGetIntegerv(GL_RENDERBUFFER_BINDING, &currentRboId);
-
- // Create a render buffer object that is backed by the EGL image.
- glGenRenderbuffers(1, &window->mColorRBO);
- glBindRenderbuffer(GL_RENDERBUFFER, window->mColorRBO);
- glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, window->mEGLImage);
-
- // Get or create an FBO for the specified dimensions
- GLuint fboId = GetOrCreateFbo(window, desc.Width, desc.Height);
-
- // Attach the new renderbuffer to the FBO
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
- glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, window->mColorRBO);
-
- // Restore previous FBO and RBO bindings
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFboId);
- glBindRenderbuffer(GL_RENDERBUFFER, currentRboId);
-
- return fboId;
-}
-
-// Unbind a currently bound DC surface
-void com_dc_unbind_surface(Window* window) {
- HRESULT hr = window->pCurrentSurface->EndDraw();
- assert(SUCCEEDED(hr));
+ // 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;
+ pTexture->GetDesc(&desc);
+ *x_offset = offset.x;
+ *y_offset = offset.y;
+
+ // Construct an EGLImage wrapper around the D3D texture for ANGLE.
+ const EGLAttrib attribs[] = { EGL_NONE };
+ window->mEGLImage = eglCreateImage(
+ window->EGLDisplay,
+ EGL_NO_CONTEXT,
+ EGL_D3D11_TEXTURE_ANGLE,
+ static_cast<EGLClientBuffer>(pTexture),
+ attribs
+ );
+
+ // Get the current FBO and RBO id, so we can restore them later
+ GLint currentFboId, currentRboId;
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFboId);
+ glGetIntegerv(GL_RENDERBUFFER_BINDING, &currentRboId);
+
+ // Create a render buffer object that is backed by the EGL image.
+ glGenRenderbuffers(1, &window->mColorRBO);
+ glBindRenderbuffer(GL_RENDERBUFFER, window->mColorRBO);
+ glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, window->mEGLImage);
+
+ // Get or create an FBO for the specified dimensions
+ GLuint fboId = GetOrCreateFbo(window, desc.Width, desc.Height);
+
+ // Attach the new renderbuffer to the FBO
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
+ glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ window->mColorRBO);
+
+ // Restore previous FBO and RBO bindings
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFboId);
+ glBindRenderbuffer(GL_RENDERBUFFER, currentRboId);
+
+ return fboId;
+ }
- glDeleteRenderbuffers(1, &window->mColorRBO);
- window->mColorRBO = 0;
+ // Unbind a currently bound DC surface
+ void com_dc_unbind_surface(Window *window) {
+ HRESULT hr = window->pCurrentSurface->EndDraw();
+ assert(SUCCEEDED(hr));
- eglDestroyImage(window->EGLDisplay, window->mEGLImage);
- window->mEGLImage = EGL_NO_IMAGE;
-}
+ glDeleteRenderbuffers(1, &window->mColorRBO);
+ window->mColorRBO = 0;
-void com_dc_begin_transaction(Window*) {}
+ eglDestroyImage(window->EGLDisplay, window->mEGLImage);
+ window->mEGLImage = EGL_NO_IMAGE;
+ }
-// Add a DC surface to the visual tree. Called per-frame to build the
-// composition.
-void com_dc_add_surface(Window* window, uint64_t id, int x, int y, int clip_x,
- int clip_y, int clip_w, int clip_h) {
- Surface surface = window->surfaces[id];
- window->mCurrentLayers.push_back(id);
+ void com_dc_begin_transaction(Window *) {
+ }
- // Place the visual - this changes frame to frame based on scroll position
- // of the slice.
- float offset_x = (float)(x + window->client_rect.left);
- float offset_y = (float)(y + window->client_rect.top);
+ // Add a DC surface to the visual tree. Called per-frame to build the composition.
+ void com_dc_add_surface(
+ Window *window,
+ uint64_t id,
+ int x,
+ int y,
+ int clip_x,
+ int clip_y,
+ int clip_w,
+ int clip_h
+ ) {
+ Surface surface = window->surfaces[id];
+ window->mCurrentLayers.push_back(id);
+
+ // Place the visual - this changes frame to frame based on scroll position
+ // 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;
+ offset_x -= VIRTUAL_OFFSET;
+ offset_y -= VIRTUAL_OFFSET;
#endif
- surface.pVisual->SetOffsetX(offset_x);
- surface.pVisual->SetOffsetY(offset_y);
-
- // Set the clip rect - converting from world space to the pre-offset space
- // that DC requires for rectangle clips.
- D2D_RECT_F clip_rect;
- clip_rect.left = clip_x - offset_x;
- clip_rect.top = clip_y - offset_y;
- clip_rect.right = clip_rect.left + clip_w;
- clip_rect.bottom = clip_rect.top + clip_h;
- surface.pVisual->SetClip(clip_rect);
-}
-
-// Finish the composition transaction, telling DC to composite
-void com_dc_end_transaction(Window* window) {
- bool same = window->mPrevLayers == window->mCurrentLayers;
-
- if (!same) {
- HRESULT hr = window->pRoot->RemoveAllVisuals();
- assert(SUCCEEDED(hr));
-
- for (auto it = window->mCurrentLayers.begin();
- it != window->mCurrentLayers.end(); ++it) {
- Surface& surface = window->surfaces[*it];
-
- // Add this visual as the last element in the visual tree (z-order is
- // implicit, based on the order tiles are added).
- hr = window->pRoot->AddVisual(surface.pVisual, FALSE, NULL);
- assert(SUCCEEDED(hr));
+ surface.pVisual->SetOffsetX(offset_x);
+ surface.pVisual->SetOffsetY(offset_y);
+
+ // Set the clip rect - converting from world space to the pre-offset space
+ // that DC requires for rectangle clips.
+ D2D_RECT_F clip_rect;
+ clip_rect.left = clip_x - offset_x;
+ clip_rect.top = clip_y - offset_y;
+ clip_rect.right = clip_rect.left + clip_w;
+ clip_rect.bottom = clip_rect.top + clip_h;
+ surface.pVisual->SetClip(clip_rect);
}
- }
- window->mPrevLayers.swap(window->mCurrentLayers);
- window->mCurrentLayers.clear();
-
- HRESULT hr = window->pDCompDevice->Commit();
- assert(SUCCEEDED(hr));
-}
+ // Finish the composition transaction, telling DC to composite
+ void com_dc_end_transaction(Window *window) {
+ bool same = window->mPrevLayers == window->mCurrentLayers;
+
+ if (!same) {
+ HRESULT hr = window->pRoot->RemoveAllVisuals();
+ assert(SUCCEEDED(hr));
+
+ for (auto it = window->mCurrentLayers.begin(); it != window->mCurrentLayers.end(); ++it) {
+ Surface &surface = window->surfaces[*it];
+
+ // Add this visual as the last element in the visual tree (z-order is implicit,
+ // based on the order tiles are added).
+ hr = window->pRoot->AddVisual(
+ surface.pVisual,
+ FALSE,
+ NULL
+ );
+ assert(SUCCEEDED(hr));
+ }
+ }
+
+ window->mPrevLayers.swap(window->mCurrentLayers);
+ window->mCurrentLayers.clear();
+
+ HRESULT hr = window->pDCompDevice->Commit();
+ assert(SUCCEEDED(hr));
+ }
-// Get a pointer to an EGL symbol
-void* com_dc_get_proc_address(const char* name) {
- return eglGetProcAddress(name);
-}
+ // Get a pointer to an EGL symbol
+ void *com_dc_get_proc_address(const char *name) {
+ return eglGetProcAddress(name);
+ }
}
diff --git a/third_party/webrender/example-compositor/compositor-windows/src/lib.rs b/third_party/webrender/example-compositor/compositor-windows/src/lib.rs
index df15b0348ab..18b80b5d1e9 100644
--- a/third_party/webrender/example-compositor/compositor-windows/src/lib.rs
+++ b/third_party/webrender/example-compositor/compositor-windows/src/lib.rs
@@ -88,8 +88,6 @@ extern {
);
fn com_dc_end_transaction(window: *mut Window);
-
- fn deinit(window: *mut Window);
}
pub fn create_window(
@@ -261,7 +259,3 @@ pub fn swap_buffers(window: *mut Window) {
com_dc_swap_buffers(window);
}
}
-
-pub fn deinit(window: *mut Window) {
- todo!()
-}
diff --git a/third_party/webrender/example-compositor/compositor/Cargo.toml b/third_party/webrender/example-compositor/compositor/Cargo.toml
index 02c6ebe0ce2..d505e9ad295 100644
--- a/third_party/webrender/example-compositor/compositor/Cargo.toml
+++ b/third_party/webrender/example-compositor/compositor/Cargo.toml
@@ -7,10 +7,7 @@ license = "MPL-2.0"
[dependencies]
webrender = { path = "../../webrender" }
-gleam = "0.15"
+gleam = "0.12.0"
[target.'cfg(windows)'.dependencies]
compositor-windows = { path = "../compositor-windows" }
-
-[target.'cfg(target_os = "linux")'.dependencies]
-compositor-wayland = { path = "../compositor-wayland" }
diff --git a/third_party/webrender/example-compositor/compositor/src/main.rs b/third_party/webrender/example-compositor/compositor/src/main.rs
index fef9438ec20..b2a7aac3a94 100644
--- a/third_party/webrender/example-compositor/compositor/src/main.rs
+++ b/third_party/webrender/example-compositor/compositor/src/main.rs
@@ -16,12 +16,10 @@ use euclid::Angle;
use gleam::gl;
use std::ffi::CString;
use std::sync::mpsc;
-use webrender::{CompositorSurfaceTransform, Transaction, api::*, euclid::point2};
+use webrender::api::*;
use webrender::api::units::*;
#[cfg(target_os = "windows")]
use compositor_windows as compositor;
-#[cfg(target_os = "linux")]
-use compositor_wayland as compositor;
use std::{env, f32, process};
// A very hacky integration with DirectComposite. It proxies calls from the compositor
@@ -44,7 +42,6 @@ impl webrender::Compositor for DirectCompositeInterface {
fn create_surface(
&mut self,
id: webrender::NativeSurfaceId,
- _virtual_offset: DeviceIntPoint,
tile_size: DeviceIntSize,
is_opaque: bool,
) {
@@ -92,7 +89,6 @@ impl webrender::Compositor for DirectCompositeInterface {
&mut self,
id: webrender::NativeTileId,
dirty_rect: DeviceIntRect,
- _valid_rect: DeviceIntRect,
) -> webrender::NativeSurfaceInfo {
let (fbo_id, x, y) = compositor::bind_surface(
self.window,
@@ -122,15 +118,14 @@ impl webrender::Compositor for DirectCompositeInterface {
fn add_surface(
&mut self,
id: webrender::NativeSurfaceId,
- transform: CompositorSurfaceTransform,
+ position: DeviceIntPoint,
clip_rect: DeviceIntRect,
- _image_rendering: ImageRendering,
) {
compositor::add_surface(
self.window,
id.0,
- transform.transform_point2d(point2(0., 0.)).unwrap().x as i32,
- transform.transform_point2d(point2(0., 0.)).unwrap().y as i32,
+ position.x,
+ position.y,
clip_rect.origin.x,
clip_rect.origin.y,
clip_rect.size.width,
@@ -141,42 +136,6 @@ impl webrender::Compositor for DirectCompositeInterface {
fn end_frame(&mut self) {
compositor::end_transaction(self.window);
}
- fn create_external_surface(&mut self, _: webrender::NativeSurfaceId, _: bool) { todo!() }
-
- fn attach_external_image(
- &mut self,
- _id: webrender::NativeSurfaceId,
- _external_image: ExternalImageId
- ) {
- todo!()
- }
-
- fn enable_native_compositor(&mut self, _enable: bool) {
- todo!()
- }
-
- fn deinit(&mut self) {
- compositor::deinit(self.window);
- }
-
- fn get_capabilities(&self) -> webrender::CompositorCapabilities {
- webrender::CompositorCapabilities {
- virtual_surface_size: 1024 * 1024,
- ..Default::default()
- }
- }
-
- fn invalidate_tile(
- &mut self,
- _id: webrender::NativeTileId,
- _valid_rect: DeviceIntRect,
- ) {}
-
- fn start_compositing(
- &mut self,
- _dirty_rects: &[DeviceIntRect],
- _opaque_rects: &[DeviceIntRect],
- ) {}
}
// Simplisitic implementation of the WR notifier interface to know when a frame
@@ -200,7 +159,7 @@ impl RenderNotifier for Notifier {
})
}
- fn wake_up(&self, _composite_needed: bool) {
+ fn wake_up(&self) {
}
fn new_frame_ready(&self,
@@ -222,7 +181,7 @@ fn push_rotated_rect(
time: f32,
) {
let color = color.scale_rgb(time);
- let rotation = LayoutTransform::rotation(
+ let rotation = LayoutTransform::create_rotation(
0.0,
0.0,
1.0,
@@ -235,16 +194,13 @@ fn push_rotated_rect(
);
let transform = rotation
.pre_translate(-transform_origin)
- .then_translate(transform_origin);
+ .post_translate(transform_origin);
let spatial_id = builder.push_reference_frame(
LayoutPoint::zero(),
spatial_id,
TransformStyle::Flat,
PropertyBinding::Value(transform),
- ReferenceFrameKind::Transform {
- is_2d_scale_translation: false,
- should_snap: false,
- },
+ ReferenceFrameKind::Transform,
);
builder.push_rect(
&CommonItemProperties::new(
@@ -279,7 +235,7 @@ fn build_display_list(
let scroll_space_info = builder.define_scroll_frame(
&fixed_space_info,
- scroll_id,
+ Some(scroll_id),
LayoutRect::new(LayoutPoint::zero(), layout_size),
LayoutRect::new(LayoutPoint::zero(), layout_size),
ScrollSensitivity::Script,
@@ -333,32 +289,6 @@ fn build_display_list(
0.1,
time,
);
-
- push_rotated_rect(
- builder,
- LayoutRect::new(
- LayoutPoint::new(100.0, 600.0),
- LayoutSize::new(size_factor * 400.0, size_factor * 400.0),
- ),
- ColorF::new(1.0, 1.0, 0.0, 1.0),
- scroll_space_info.spatial_id,
- root_pipeline_id,
- time,
- time,
- );
-
- push_rotated_rect(
- builder,
- LayoutRect::new(
- LayoutPoint::new(700.0, 600.0),
- LayoutSize::new(size_factor * 400.0, size_factor * 400.0),
- ),
- ColorF::new(0.0, 1.0, 1.0, 1.0),
- scroll_space_info.spatial_id,
- root_pipeline_id,
- time,
- time,
- );
}
#[derive(Debug, Copy, Clone)]
@@ -428,15 +358,13 @@ fn main() {
} else {
webrender::CompositorConfig::Draw {
max_partial_present_rects: 0,
- draw_previous_partial_present_regions: false,
- partial_present: None,
}
};
let opts = webrender::RendererOptions {
clear_color: Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
debug_flags,
+ enable_picture_caching: true,
compositor_config,
- surface_origin_is_top_left: false,
..webrender::RendererOptions::default()
};
let (tx, rx) = mpsc::channel();
@@ -455,9 +383,10 @@ fn main() {
notifier,
opts,
None,
+ device_size,
).unwrap();
- let mut api = sender.create_api();
- let document_id = api.add_document(device_size);
+ let api = sender.create_api();
+ let document_id = api.add_document(device_size, 0);
let device_pixel_ratio = 1.0;
let mut current_epoch = Epoch(0);
let root_pipeline_id = PipelineId(0, 0);
@@ -470,7 +399,7 @@ fn main() {
txn.set_root_pipeline(root_pipeline_id);
if let Invalidations::Scrolling = inv_mode {
- let mut root_builder = DisplayListBuilder::new(root_pipeline_id);
+ let mut root_builder = DisplayListBuilder::new(root_pipeline_id, layout_size);
build_display_list(
&mut root_builder,
@@ -490,7 +419,7 @@ fn main() {
);
}
- txn.generate_frame(0);
+ txn.generate_frame();
api.send_transaction(document_id, txn);
// Tick the compositor (in this sample, we don't block on UI events)
@@ -500,7 +429,7 @@ fn main() {
// Update and render. This will invoke the native compositor interface implemented above
// as required.
renderer.update();
- renderer.render(device_size, 0).unwrap();
+ renderer.render(device_size).unwrap();
let _ = renderer.flush_pipeline_info();
// Construct a simple display list that can be drawn and composited by DC.
@@ -508,7 +437,7 @@ fn main() {
match inv_mode {
Invalidations::Small | Invalidations::Large => {
- let mut root_builder = DisplayListBuilder::new(root_pipeline_id);
+ let mut root_builder = DisplayListBuilder::new(root_pipeline_id, layout_size);
build_display_list(
&mut root_builder,
@@ -537,7 +466,7 @@ fn main() {
}
}
- txn.generate_frame(0);
+ txn.generate_frame();
api.send_transaction(document_id, txn);
current_epoch.0 += 1;
time += 0.001;