зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1598448 - Change compositor example to use EGLImage instead of pbuffer. r=sotaro
Update the example compositor implementation to use the faster EGLImage technique that the Gecko implementation now uses. Differential Revision: https://phabricator.services.mozilla.com/D54185 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
b30d1c40a4
Коммит
ae587eeebc
|
@ -10,13 +10,18 @@
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define EGL_EGL_PROTOTYPES 1
|
#define EGL_EGL_PROTOTYPES 1
|
||||||
#define EGL_EGLEXT_PROTOTYPES 1
|
#define EGL_EGLEXT_PROTOTYPES 1
|
||||||
|
#define GL_GLEXT_PROTOTYPES 1
|
||||||
#include "EGL/egl.h"
|
#include "EGL/egl.h"
|
||||||
#include "EGL/eglext.h"
|
#include "EGL/eglext.h"
|
||||||
#include "EGL/eglext_angle.h"
|
#include "EGL/eglext_angle.h"
|
||||||
#include "GL/gl.h"
|
#include "GL/gl.h"
|
||||||
|
#include "GLES/gl.h"
|
||||||
|
#include "GLES/glext.h"
|
||||||
|
#include "GLES3/gl3.h"
|
||||||
|
|
||||||
// The OS compositor representation of a picture cache tile.
|
// The OS compositor representation of a picture cache tile.
|
||||||
struct Tile {
|
struct Tile {
|
||||||
|
@ -26,6 +31,13 @@ struct Tile {
|
||||||
IDCompositionVisual2 *pVisual;
|
IDCompositionVisual2 *pVisual;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CachedFrameBuffer {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
GLuint fboId;
|
||||||
|
GLuint depthRboId;
|
||||||
|
};
|
||||||
|
|
||||||
struct Window {
|
struct Window {
|
||||||
// Win32 window details
|
// Win32 window details
|
||||||
HWND hWnd;
|
HWND hWnd;
|
||||||
|
@ -50,8 +62,9 @@ struct Window {
|
||||||
EGLSurface fb_surface;
|
EGLSurface fb_surface;
|
||||||
|
|
||||||
// The currently bound surface, valid during bind() and unbind()
|
// The currently bound surface, valid during bind() and unbind()
|
||||||
EGLSurface current_surface;
|
|
||||||
IDCompositionSurface *pCurrentSurface;
|
IDCompositionSurface *pCurrentSurface;
|
||||||
|
EGLImage mEGLImage;
|
||||||
|
GLuint mColorRBO;
|
||||||
|
|
||||||
// The root of the DC visual tree. Nothing is drawn on this, but
|
// The root of the DC visual tree. Nothing is drawn on this, but
|
||||||
// all child tiles are parented to here.
|
// all child tiles are parented to here.
|
||||||
|
@ -59,10 +72,50 @@ struct Window {
|
||||||
IDCompositionVisualDebug *pVisualDebug;
|
IDCompositionVisualDebug *pVisualDebug;
|
||||||
// Maps the WR surface IDs to the DC representation of each tile.
|
// Maps the WR surface IDs to the DC representation of each tile.
|
||||||
std::map<uint64_t, Tile> tiles;
|
std::map<uint64_t, Tile> tiles;
|
||||||
|
std::vector<CachedFrameBuffer> mFrameBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK WndProc(
|
static LRESULT CALLBACK WndProc(
|
||||||
HWND hwnd,
|
HWND hwnd,
|
||||||
UINT message,
|
UINT message,
|
||||||
|
@ -86,6 +139,7 @@ extern "C" {
|
||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
window->enable_compositor = enable_compositor;
|
window->enable_compositor = enable_compositor;
|
||||||
|
window->mEGLImage = EGL_NO_IMAGE;
|
||||||
|
|
||||||
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
|
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
@ -284,7 +338,7 @@ extern "C" {
|
||||||
delete window;
|
delete window;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool com_dc_tick(Window *window) {
|
bool com_dc_tick(Window *) {
|
||||||
// Check and dispatch the windows event loop
|
// Check and dispatch the windows event loop
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
@ -356,7 +410,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a DC surface to allow issuing GL commands to it
|
// Bind a DC surface to allow issuing GL commands to it
|
||||||
void com_dc_bind_surface(
|
GLuint com_dc_bind_surface(
|
||||||
Window *window,
|
Window *window,
|
||||||
uint64_t id,
|
uint64_t id,
|
||||||
int *x_offset,
|
int *x_offset,
|
||||||
|
@ -395,35 +449,44 @@ extern "C" {
|
||||||
offset.y -= dirty_y0;
|
offset.y -= dirty_y0;
|
||||||
assert(SUCCEEDED(hr));
|
assert(SUCCEEDED(hr));
|
||||||
pTexture->GetDesc(&desc);
|
pTexture->GetDesc(&desc);
|
||||||
|
|
||||||
// Construct an EGL off-screen surface that is bound to the DC surface
|
|
||||||
EGLint buffer_attribs[] = {
|
|
||||||
EGL_WIDTH, desc.Width,
|
|
||||||
EGL_HEIGHT, desc.Height,
|
|
||||||
EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
window->current_surface = eglCreatePbufferFromClientBuffer(
|
|
||||||
window->EGLDisplay,
|
|
||||||
EGL_D3D_TEXTURE_ANGLE,
|
|
||||||
pTexture,
|
|
||||||
window->config,
|
|
||||||
buffer_attribs
|
|
||||||
);
|
|
||||||
assert(window->current_surface != EGL_NO_SURFACE);
|
|
||||||
|
|
||||||
// Make EGL current on the DC surface
|
|
||||||
EGLBoolean ok = eglMakeCurrent(
|
|
||||||
window->EGLDisplay,
|
|
||||||
window->current_surface,
|
|
||||||
window->current_surface,
|
|
||||||
window->EGLContext
|
|
||||||
);
|
|
||||||
assert(ok);
|
|
||||||
|
|
||||||
*x_offset = offset.x;
|
*x_offset = offset.x;
|
||||||
*y_offset = offset.y;
|
*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, ¤tFboId);
|
||||||
|
glGetIntegerv(GL_RENDERBUFFER_BINDING, ¤tRboId);
|
||||||
|
|
||||||
|
// 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
|
// Unbind a currently bound DC surface
|
||||||
|
@ -431,7 +494,11 @@ extern "C" {
|
||||||
HRESULT hr = window->pCurrentSurface->EndDraw();
|
HRESULT hr = window->pCurrentSurface->EndDraw();
|
||||||
assert(SUCCEEDED(hr));
|
assert(SUCCEEDED(hr));
|
||||||
|
|
||||||
eglDestroySurface(window->EGLDisplay, window->current_surface);
|
glDeleteRenderbuffers(1, &window->mColorRBO);
|
||||||
|
window->mColorRBO = 0;
|
||||||
|
|
||||||
|
eglDestroyImage(window->EGLDisplay, window->mEGLImage);
|
||||||
|
window->mEGLImage = EGL_NO_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At the start of a transaction, remove all visuals from the tree.
|
// At the start of a transaction, remove all visuals from the tree.
|
||||||
|
@ -467,8 +534,8 @@ extern "C" {
|
||||||
|
|
||||||
// Place the visual - this changes frame to frame based on scroll position
|
// Place the visual - this changes frame to frame based on scroll position
|
||||||
// of the slice.
|
// of the slice.
|
||||||
int offset_x = x + window->client_rect.left;
|
float offset_x = (float) (x + window->client_rect.left);
|
||||||
int offset_y = y + window->client_rect.top;
|
float offset_y = (float) (y + window->client_rect.top);
|
||||||
tile.pVisual->SetOffsetX(offset_x);
|
tile.pVisual->SetOffsetX(offset_x);
|
||||||
tile.pVisual->SetOffsetY(offset_y);
|
tile.pVisual->SetOffsetY(offset_y);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ extern {
|
||||||
dirty_y0: i32,
|
dirty_y0: i32,
|
||||||
dirty_width: i32,
|
dirty_width: i32,
|
||||||
dirty_height: i32,
|
dirty_height: i32,
|
||||||
);
|
) -> u32;
|
||||||
fn com_dc_unbind_surface(window: *mut Window);
|
fn com_dc_unbind_surface(window: *mut Window);
|
||||||
|
|
||||||
fn com_dc_begin_transaction(window: *mut Window);
|
fn com_dc_begin_transaction(window: *mut Window);
|
||||||
|
@ -130,12 +130,12 @@ pub fn bind_surface(
|
||||||
dirty_y0: i32,
|
dirty_y0: i32,
|
||||||
dirty_width: i32,
|
dirty_width: i32,
|
||||||
dirty_height: i32,
|
dirty_height: i32,
|
||||||
) -> (i32, i32) {
|
) -> (u32, i32, i32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut x_offset = 0;
|
let mut x_offset = 0;
|
||||||
let mut y_offset = 0;
|
let mut y_offset = 0;
|
||||||
|
|
||||||
com_dc_bind_surface(
|
let fbo_id = com_dc_bind_surface(
|
||||||
window,
|
window,
|
||||||
id,
|
id,
|
||||||
&mut x_offset,
|
&mut x_offset,
|
||||||
|
@ -146,7 +146,7 @@ pub fn bind_surface(
|
||||||
dirty_height,
|
dirty_height,
|
||||||
);
|
);
|
||||||
|
|
||||||
(x_offset, y_offset)
|
(fbo_id, x_offset, y_offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
||||||
id: webrender::NativeSurfaceId,
|
id: webrender::NativeSurfaceId,
|
||||||
dirty_rect: DeviceIntRect,
|
dirty_rect: DeviceIntRect,
|
||||||
) -> webrender::NativeSurfaceInfo {
|
) -> webrender::NativeSurfaceInfo {
|
||||||
let (x, y) = compositor::bind_surface(
|
let (fbo_id, x, y) = compositor::bind_surface(
|
||||||
self.window,
|
self.window,
|
||||||
id.0,
|
id.0,
|
||||||
dirty_rect.origin.x,
|
dirty_rect.origin.x,
|
||||||
|
@ -76,7 +76,7 @@ impl webrender::Compositor for DirectCompositeInterface {
|
||||||
|
|
||||||
webrender::NativeSurfaceInfo {
|
webrender::NativeSurfaceInfo {
|
||||||
origin: DeviceIntPoint::new(x, y),
|
origin: DeviceIntPoint::new(x, y),
|
||||||
fbo_id: 0,
|
fbo_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче