mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
Bug 1607352 - Support DirectComposition virtual surface API. r=sotaro
Adds an #ifdef to the DCLayerTree implementation that allows selecting whether to use the virtual surface API (enabled by default) or the regular DC surface API. For now, this is a compile-time switch. As a follow up to this, we will support both options at runtime (for example, using the regular surface API for surfaces that have holes or translucency). Differential Revision: https://phabricator.services.mozilla.com/D58870 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
5f422b375c
commit
74722337a2
@ -50,11 +50,15 @@ DCLayerTree::DCLayerTree(gl::GLContext* aGL, EGLConfig aEGLConfig,
|
||||
mDevice(aDevice),
|
||||
mCompositionDevice(aCompositionDevice),
|
||||
mDebugCounter(false),
|
||||
mDebugVisualRedrawRegions(false) {}
|
||||
mDebugVisualRedrawRegions(false),
|
||||
mEGLImage(EGL_NO_IMAGE),
|
||||
mColorRBO(0) {}
|
||||
|
||||
DCLayerTree::~DCLayerTree() {
|
||||
const auto gl = GetGLContext();
|
||||
|
||||
DestroyEGLSurface();
|
||||
|
||||
// Delete any cached FBO objects
|
||||
for (auto it = mFrameBuffers.begin(); it != mFrameBuffers.end(); ++it) {
|
||||
gl->fDeleteRenderbuffers(1, &it->depthRboId);
|
||||
@ -210,23 +214,34 @@ void DCLayerTree::CompositorEndFrame() {
|
||||
void DCLayerTree::Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset,
|
||||
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect) {
|
||||
auto surface = GetSurface(aId.surface_id);
|
||||
auto layer = surface->GetLayer(aId.x, aId.y);
|
||||
wr::DeviceIntPoint targetOffset{0, 0};
|
||||
|
||||
*aFboId = layer->CreateEGLSurfaceForCompositionSurface(aDirtyRect, aOffset);
|
||||
mCurrentId = Some(aId);
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
wr::DeviceIntSize tileSize = surface->GetTileSize();
|
||||
RefPtr<IDCompositionSurface> compositionSurface =
|
||||
surface->GetCompositionSurface();
|
||||
targetOffset.x = VIRTUAL_OFFSET + tileSize.width * aId.x;
|
||||
targetOffset.y = VIRTUAL_OFFSET + tileSize.height * aId.y;
|
||||
#else
|
||||
auto layer = surface->GetLayer(aId.x, aId.y);
|
||||
RefPtr<IDCompositionSurface> compositionSurface =
|
||||
layer->GetCompositionSurface();
|
||||
#endif
|
||||
|
||||
*aFboId = CreateEGLSurfaceForCompositionSurface(
|
||||
aDirtyRect, aOffset, compositionSurface, targetOffset);
|
||||
mCurrentSurface = Some(compositionSurface);
|
||||
}
|
||||
|
||||
void DCLayerTree::Unbind() {
|
||||
if (mCurrentId.isNothing()) {
|
||||
if (mCurrentSurface.isNothing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto id = mCurrentId.ref();
|
||||
auto surface = GetSurface(id.surface_id);
|
||||
auto layer = surface->GetLayer(id.x, id.y);
|
||||
RefPtr<IDCompositionSurface> surface = mCurrentSurface.ref();
|
||||
surface->EndDraw();
|
||||
|
||||
layer->EndDraw();
|
||||
mCurrentId = Nothing();
|
||||
mCurrentSurface = Nothing();
|
||||
}
|
||||
|
||||
void DCLayerTree::CreateSurface(wr::NativeSurfaceId aId,
|
||||
@ -274,6 +289,13 @@ void DCLayerTree::AddSurface(wr::NativeSurfaceId aId,
|
||||
const auto layer = it->second.get();
|
||||
const auto visual = layer->GetVisual();
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
layer->UpdateAllocatedRect();
|
||||
|
||||
aPosition.x -= VIRTUAL_OFFSET;
|
||||
aPosition.y -= VIRTUAL_OFFSET;
|
||||
#endif
|
||||
|
||||
// Place the visual - this changes frame to frame based on scroll position
|
||||
// of the slice.
|
||||
visual->SetOffsetX(aPosition.x);
|
||||
@ -336,7 +358,10 @@ GLuint DCLayerTree::GetOrCreateFbo(int aWidth, int aHeight) {
|
||||
|
||||
DCSurface::DCSurface(wr::DeviceIntSize aTileSize, bool aIsOpaque,
|
||||
DCLayerTree* aDCLayerTree)
|
||||
: mDCLayerTree(aDCLayerTree), mTileSize(aTileSize), mIsOpaque(aIsOpaque) {}
|
||||
: mDCLayerTree(aDCLayerTree),
|
||||
mTileSize(aTileSize),
|
||||
mIsOpaque(aIsOpaque),
|
||||
mAllocatedRectDirty(true) {}
|
||||
|
||||
DCSurface::~DCSurface() {}
|
||||
|
||||
@ -349,6 +374,20 @@ bool DCSurface::Initialize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
DXGI_ALPHA_MODE alpha_mode =
|
||||
mIsOpaque ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
|
||||
|
||||
hr = dCompDevice->CreateVirtualSurface(VIRTUAL_OFFSET * 2, VIRTUAL_OFFSET * 2,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, alpha_mode,
|
||||
getter_AddRefs(mVirtualSurface));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Bind the surface memory to this visual
|
||||
hr = mVisual->SetContent(mVirtualSurface);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -362,17 +401,53 @@ void DCSurface::CreateTile(int aX, int aY) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
mAllocatedRectDirty = true;
|
||||
#else
|
||||
mVisual->AddVisual(layer->GetVisual(), FALSE, NULL);
|
||||
#endif
|
||||
|
||||
mDCLayers[key] = std::move(layer);
|
||||
}
|
||||
|
||||
void DCSurface::DestroyTile(int aX, int aY) {
|
||||
TileKey key(aX, aY);
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
mAllocatedRectDirty = true;
|
||||
#else
|
||||
auto layer = GetLayer(aX, aY);
|
||||
mVisual->RemoveVisual(layer->GetVisual());
|
||||
#endif
|
||||
mDCLayers.erase(key);
|
||||
}
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
void DCSurface::UpdateAllocatedRect() {
|
||||
if (mAllocatedRectDirty) {
|
||||
RECT rect = {1000000, 1000000, -1000000, -1000000};
|
||||
|
||||
for (auto it = mDCLayers.begin(); it != mDCLayers.end(); ++it) {
|
||||
int x = it->first.mX;
|
||||
int y = it->first.mY;
|
||||
|
||||
rect.left = std::min((int)rect.left, x * mTileSize.width);
|
||||
rect.right = std::max((int)rect.right, (x + 1) * mTileSize.width);
|
||||
|
||||
rect.top = std::min((int)rect.top, y * mTileSize.height);
|
||||
rect.bottom = std::max((int)rect.bottom, (y + 1) * mTileSize.height);
|
||||
}
|
||||
|
||||
rect.left += VIRTUAL_OFFSET;
|
||||
rect.top += VIRTUAL_OFFSET;
|
||||
rect.bottom += VIRTUAL_OFFSET;
|
||||
rect.right += VIRTUAL_OFFSET;
|
||||
|
||||
mVirtualSurface->Trim(&rect, 1);
|
||||
mAllocatedRectDirty = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DCLayer* DCSurface::GetLayer(int aX, int aY) const {
|
||||
TileKey key(aX, aY);
|
||||
auto layer_it = mDCLayers.find(key);
|
||||
@ -380,18 +455,17 @@ DCLayer* DCSurface::GetLayer(int aX, int aY) const {
|
||||
return layer_it->second.get();
|
||||
}
|
||||
|
||||
DCLayer::DCLayer(DCLayerTree* aDCLayerTree)
|
||||
: mDCLayerTree(aDCLayerTree), mEGLImage(EGL_NO_IMAGE), mColorRBO(0) {}
|
||||
DCLayer::DCLayer(DCLayerTree* aDCLayerTree) : mDCLayerTree(aDCLayerTree) {}
|
||||
|
||||
DCLayer::~DCLayer() { DestroyEGLSurface(); }
|
||||
DCLayer::~DCLayer() {}
|
||||
|
||||
bool DCLayer::Initialize(int aX, int aY, wr::DeviceIntSize aSize,
|
||||
bool aIsOpaque) {
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
return false;
|
||||
}
|
||||
mBufferSize = LayoutDeviceIntSize(aSize.width, aSize.height);
|
||||
|
||||
#ifndef USE_VIRTUAL_SURFACES
|
||||
HRESULT hr;
|
||||
const auto dCompDevice = mDCLayerTree->GetCompositionDevice();
|
||||
hr = dCompDevice->CreateVisual(getter_AddRefs(mVisual));
|
||||
@ -415,10 +489,12 @@ bool DCLayer::Initialize(int aX, int aY, wr::DeviceIntSize aSize,
|
||||
// Scroll offsets get applied to the parent visual only.
|
||||
mVisual->SetOffsetX(aX * aSize.width);
|
||||
mVisual->SetOffsetY(aY * aSize.height);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef USE_VIRTUAL_SURFACES
|
||||
RefPtr<IDCompositionSurface> DCLayer::CreateCompositionSurface(
|
||||
wr::DeviceIntSize aSize, bool aIsOpaque) {
|
||||
HRESULT hr;
|
||||
@ -437,45 +513,38 @@ RefPtr<IDCompositionSurface> DCLayer::CreateCompositionSurface(
|
||||
}
|
||||
return compositionSurface;
|
||||
}
|
||||
#endif
|
||||
|
||||
GLuint DCLayer::CreateEGLSurfaceForCompositionSurface(
|
||||
wr::DeviceIntRect aDirtyRect, wr::DeviceIntPoint* aOffset) {
|
||||
MOZ_ASSERT(mCompositionSurface.get());
|
||||
GLuint DCLayerTree::CreateEGLSurfaceForCompositionSurface(
|
||||
wr::DeviceIntRect aDirtyRect, wr::DeviceIntPoint* aOffset,
|
||||
RefPtr<IDCompositionSurface> aCompositionSurface,
|
||||
wr::DeviceIntPoint aSurfaceOffset) {
|
||||
MOZ_ASSERT(aCompositionSurface.get());
|
||||
|
||||
HRESULT hr;
|
||||
const auto gl = mDCLayerTree->GetGLContext();
|
||||
const auto gl = GetGLContext();
|
||||
RefPtr<ID3D11Texture2D> backBuf;
|
||||
POINT offset;
|
||||
|
||||
LayoutDeviceIntRect dirtyRect(aDirtyRect.origin.x, aDirtyRect.origin.y,
|
||||
aDirtyRect.size.width, aDirtyRect.size.height);
|
||||
|
||||
RECT update_rect;
|
||||
update_rect.left = dirtyRect.X();
|
||||
update_rect.top = dirtyRect.Y();
|
||||
update_rect.right = dirtyRect.XMost();
|
||||
update_rect.bottom = dirtyRect.YMost();
|
||||
update_rect.left = aSurfaceOffset.x + aDirtyRect.origin.x;
|
||||
update_rect.top = aSurfaceOffset.y + aDirtyRect.origin.y;
|
||||
update_rect.right = update_rect.left + aDirtyRect.size.width;
|
||||
update_rect.bottom = update_rect.top + aDirtyRect.size.height;
|
||||
|
||||
RECT* rect = &update_rect;
|
||||
if (StaticPrefs::gfx_webrender_compositor_max_update_rects_AtStartup() <= 0) {
|
||||
// Update entire surface
|
||||
rect = nullptr;
|
||||
}
|
||||
|
||||
hr = mCompositionSurface->BeginDraw(rect, __uuidof(ID3D11Texture2D),
|
||||
hr = aCompositionSurface->BeginDraw(&update_rect, __uuidof(ID3D11Texture2D),
|
||||
(void**)getter_AddRefs(backBuf), &offset);
|
||||
if (FAILED(hr)) {
|
||||
gfxCriticalNote << "DCompositionSurface::BeginDraw failed: "
|
||||
<< gfx::hexa(hr) << "dirtyRect: " << dirtyRect;
|
||||
<< gfx::hexa(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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.
|
||||
offset.x -= dirtyRect.X();
|
||||
offset.y -= dirtyRect.Y();
|
||||
offset.x -= aDirtyRect.origin.x;
|
||||
offset.y -= aDirtyRect.origin.y;
|
||||
|
||||
// Texture size could be diffrent from mBufferSize.
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
backBuf->GetDesc(&desc);
|
||||
|
||||
@ -500,7 +569,7 @@ GLuint DCLayer::CreateEGLSurfaceForCompositionSurface(
|
||||
gl->fEGLImageTargetRenderbufferStorage(LOCAL_GL_RENDERBUFFER, mEGLImage);
|
||||
|
||||
// Get or create an FBO for the specified dimensions
|
||||
GLuint fboId = mDCLayerTree->GetOrCreateFbo(desc.Width, desc.Height);
|
||||
GLuint fboId = GetOrCreateFbo(desc.Width, desc.Height);
|
||||
|
||||
// Attach the new renderbuffer to the FBO
|
||||
gl->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, fboId);
|
||||
@ -518,8 +587,8 @@ GLuint DCLayer::CreateEGLSurfaceForCompositionSurface(
|
||||
return fboId;
|
||||
}
|
||||
|
||||
void DCLayer::DestroyEGLSurface() {
|
||||
const auto gl = mDCLayerTree->GetGLContext();
|
||||
void DCLayerTree::DestroyEGLSurface() {
|
||||
const auto gl = GetGLContext();
|
||||
|
||||
if (mColorRBO) {
|
||||
gl->fDeleteRenderbuffers(1, &mColorRBO);
|
||||
@ -534,15 +603,5 @@ void DCLayer::DestroyEGLSurface() {
|
||||
}
|
||||
}
|
||||
|
||||
void DCLayer::EndDraw() {
|
||||
MOZ_ASSERT(mCompositionSurface.get());
|
||||
if (!mCompositionSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCompositionSurface->EndDraw();
|
||||
DestroyEGLSurface();
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
@ -23,6 +23,7 @@ struct IDCompositionSurface;
|
||||
struct IDCompositionTarget;
|
||||
struct IDCompositionVisual2;
|
||||
struct IDXGISwapChain1;
|
||||
struct IDCompositionVirtualSurface;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -32,6 +33,15 @@ class GLContext;
|
||||
|
||||
namespace wr {
|
||||
|
||||
#define USE_VIRTUAL_SURFACES
|
||||
|
||||
// DirectComposition virtual surfaces are zero based, but WR picture cache
|
||||
// bounds can potentially have a negative origin. Shift all the picture cache
|
||||
// coordinates by a large fixed amount, such that we don't need to re-create
|
||||
// the surface if the picture cache origin becomes negative due to adding more
|
||||
// tiles to the above / left.
|
||||
#define VIRTUAL_OFFSET 512 * 1024
|
||||
|
||||
class DCLayer;
|
||||
class DCSurface;
|
||||
|
||||
@ -81,6 +91,11 @@ class DCLayerTree {
|
||||
bool Initialize(HWND aHwnd);
|
||||
bool MaybeUpdateDebugCounter();
|
||||
bool MaybeUpdateDebugVisualRedrawRegions();
|
||||
void DestroyEGLSurface();
|
||||
GLuint CreateEGLSurfaceForCompositionSurface(
|
||||
wr::DeviceIntRect aDirtyRect, wr::DeviceIntPoint* aOffset,
|
||||
RefPtr<IDCompositionSurface> aCompositionSurface,
|
||||
wr::DeviceIntPoint aSurfaceOffset);
|
||||
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
EGLConfig mEGLConfig;
|
||||
@ -95,7 +110,15 @@ class DCLayerTree {
|
||||
bool mDebugCounter;
|
||||
bool mDebugVisualRedrawRegions;
|
||||
|
||||
Maybe<wr::NativeTileId> mCurrentId;
|
||||
Maybe<RefPtr<IDCompositionSurface>> mCurrentSurface;
|
||||
|
||||
// The EGL image that is bound to the D3D texture provided by
|
||||
// DirectComposition.
|
||||
EGLImage mEGLImage;
|
||||
|
||||
// The GL render buffer ID that maps the EGLImage to an RBO for attaching to
|
||||
// an FBO.
|
||||
GLuint mColorRBO;
|
||||
|
||||
struct SurfaceIdHashFn {
|
||||
std::size_t operator()(const wr::NativeSurfaceId& aId) const {
|
||||
@ -153,6 +176,16 @@ class DCSurface {
|
||||
int32_t mY;
|
||||
};
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
wr::DeviceIntSize GetTileSize() const { return mTileSize; }
|
||||
|
||||
IDCompositionVirtualSurface* GetCompositionSurface() const {
|
||||
return mVirtualSurface;
|
||||
}
|
||||
|
||||
void UpdateAllocatedRect();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
DCLayerTree* mDCLayerTree;
|
||||
|
||||
@ -170,7 +203,12 @@ class DCSurface {
|
||||
|
||||
wr::DeviceIntSize mTileSize;
|
||||
bool mIsOpaque;
|
||||
bool mAllocatedRectDirty;
|
||||
std::unordered_map<TileKey, UniquePtr<DCLayer>, TileKeyHashFn> mDCLayers;
|
||||
|
||||
#ifdef USE_VIRTUAL_SURFACES
|
||||
RefPtr<IDCompositionVirtualSurface> mVirtualSurface;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@ -182,10 +220,8 @@ class DCLayer {
|
||||
explicit DCLayer(DCLayerTree* aDCLayerTree);
|
||||
~DCLayer();
|
||||
bool Initialize(int aX, int aY, wr::DeviceIntSize aSize, bool aIsOpaque);
|
||||
GLuint CreateEGLSurfaceForCompositionSurface(wr::DeviceIntRect aDirtyRect,
|
||||
wr::DeviceIntPoint* aOffset);
|
||||
void EndDraw();
|
||||
|
||||
#ifndef USE_VIRTUAL_SURFACES
|
||||
IDCompositionSurface* GetCompositionSurface() const {
|
||||
return mCompositionSurface;
|
||||
}
|
||||
@ -194,23 +230,12 @@ class DCLayer {
|
||||
protected:
|
||||
RefPtr<IDCompositionSurface> CreateCompositionSurface(wr::DeviceIntSize aSize,
|
||||
bool aIsOpaque);
|
||||
void DestroyEGLSurface();
|
||||
|
||||
DCLayerTree* mDCLayerTree;
|
||||
|
||||
RefPtr<IDCompositionSurface> mCompositionSurface;
|
||||
|
||||
// The EGL image that is bound to the D3D texture provided by
|
||||
// DirectComposition.
|
||||
EGLImage mEGLImage;
|
||||
|
||||
// The GL render buffer ID that maps the EGLImage to an RBO for attaching to
|
||||
// an FBO.
|
||||
GLuint mColorRBO;
|
||||
|
||||
LayoutDeviceIntSize mBufferSize;
|
||||
|
||||
RefPtr<IDCompositionVisual2> mVisual;
|
||||
#endif
|
||||
|
||||
DCLayerTree* mDCLayerTree;
|
||||
};
|
||||
|
||||
static inline bool operator==(const DCSurface::TileKey& a0,
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user