зеркало из https://github.com/mozilla/gecko-dev.git
Bug 655836: Flush surface A when B changes and A has a pending drawing command depending on B. r=jrmuizel
This commit is contained in:
Родитель
cf3be6c34b
Коммит
496e39c64c
|
@ -49,6 +49,7 @@
|
|||
#include "cairo-win32-refptr.h"
|
||||
#include "cairo-d2d-private-fx.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "cairo-list-private.h"
|
||||
|
||||
/* describes the type of the currently applied clip so that we can pop it */
|
||||
struct d2d_clip;
|
||||
|
@ -81,8 +82,12 @@ struct _cairo_d2d_surface {
|
|||
textRenderingState(TEXT_RENDERING_UNINITIALIZED)
|
||||
{
|
||||
_cairo_clip_init (&this->clip);
|
||||
cairo_list_init(&this->dependent_surfaces);
|
||||
}
|
||||
|
||||
~_cairo_d2d_surface();
|
||||
|
||||
|
||||
cairo_surface_t base;
|
||||
/* Device used by this surface
|
||||
* NOTE: In upstream cairo this is in the surface base class */
|
||||
|
@ -139,11 +144,23 @@ struct _cairo_d2d_surface {
|
|||
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
|
||||
RefPtr<ID3D10ShaderResourceView> buffer_sr_view;
|
||||
|
||||
|
||||
// Other d2d surfaces which depend on this one and need to be flushed if
|
||||
// it is drawn to. This is required for situations where this surface is
|
||||
// drawn to another surface, but may be modified before the other surface
|
||||
// has flushed. When the flush of the other surface then happens and the
|
||||
// drawing command is actually executed, the contents of this surface will
|
||||
// no longer be what it was when the drawing command was issued.
|
||||
cairo_list_t dependent_surfaces;
|
||||
//cairo_surface_clipper_t clipper;
|
||||
};
|
||||
typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
|
||||
|
||||
struct _cairo_d2d_surface_entry
|
||||
{
|
||||
cairo_list_t link;
|
||||
cairo_d2d_surface_t *surface;
|
||||
};
|
||||
|
||||
typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
|
||||
__in D2D1_FACTORY_TYPE factoryType,
|
||||
__in REFIID iid,
|
||||
|
|
|
@ -1053,6 +1053,25 @@ _cairo_d2d_set_clip (cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void _cairo_d2d_add_dependent_surface(cairo_d2d_surface_t *surf, cairo_d2d_surface_t *user)
|
||||
{
|
||||
_cairo_d2d_surface_entry *entry = new _cairo_d2d_surface_entry;
|
||||
entry->surface = user;
|
||||
cairo_surface_reference(&user->base);
|
||||
cairo_list_add(&entry->link, &surf->dependent_surfaces);
|
||||
};
|
||||
|
||||
static void _cairo_d2d_flush_dependent_surfaces(cairo_d2d_surface_t *surf)
|
||||
{
|
||||
_cairo_d2d_surface_entry *entry, *next;
|
||||
cairo_list_foreach_entry_safe(entry, next, _cairo_d2d_surface_entry, &surf->dependent_surfaces, link) {
|
||||
_cairo_d2d_flush(entry->surface);
|
||||
cairo_surface_destroy(&entry->surface->base);
|
||||
delete entry;
|
||||
}
|
||||
cairo_list_init(&surf->dependent_surfaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the state where the surface is ready for drawing. This will guarantee
|
||||
* the surface is in the correct state, and the correct clipping area is pushed.
|
||||
|
@ -1062,6 +1081,7 @@ _cairo_d2d_set_clip (cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip)
|
|||
static void _begin_draw_state(cairo_d2d_surface_t* surface)
|
||||
{
|
||||
if (!surface->isDrawing) {
|
||||
_cairo_d2d_flush_dependent_surfaces(surface);
|
||||
surface->rt->BeginDraw();
|
||||
surface->isDrawing = true;
|
||||
}
|
||||
|
@ -1778,6 +1798,9 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
|
|||
_cairo_d2d_update_surface_bitmap(srcSurf);
|
||||
_cairo_d2d_flush(srcSurf);
|
||||
|
||||
// Mark a dependency on the source surface.
|
||||
_cairo_d2d_add_dependent_surface(srcSurf, d2dsurf);
|
||||
|
||||
if (pattern->extend == CAIRO_EXTEND_NONE) {
|
||||
ID2D1Bitmap *srcSurfBitmap = srcSurf->surfaceBitmap;
|
||||
d2dsurf->rt->CreateBitmap(
|
||||
|
@ -2328,6 +2351,18 @@ _cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_de
|
|||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
||||
}
|
||||
|
||||
_cairo_d2d_surface::~_cairo_d2d_surface()
|
||||
{
|
||||
_cairo_d2d_surface_entry *entry, *next;
|
||||
cairo_list_foreach_entry_safe(entry, next, _cairo_d2d_surface_entry, &dependent_surfaces, link) {
|
||||
// We do not need to flush, the contents of our texture has not changed,
|
||||
// our users have their own reference and can just use it later.
|
||||
cairo_surface_destroy(&entry->surface->base);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Implementation
|
||||
static cairo_surface_t*
|
||||
_cairo_d2d_create_similar(void *surface,
|
||||
|
@ -2793,6 +2828,8 @@ _cairo_d2d_blend_surface(cairo_d2d_surface_t *dst,
|
|||
needsTransform = true;
|
||||
}
|
||||
|
||||
_cairo_d2d_add_dependent_surface(src, dst);
|
||||
|
||||
D2D1_BITMAP_INTERPOLATION_MODE interpMode =
|
||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR;
|
||||
|
||||
|
@ -2986,6 +3023,8 @@ _cairo_d2d_get_temp_rt(cairo_d2d_surface_t *surf, cairo_clip_t *clip)
|
|||
static cairo_int_status_t
|
||||
_cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds = NULL)
|
||||
{
|
||||
_cairo_d2d_flush_dependent_surfaces(surf);
|
||||
|
||||
int numPaths = 0;
|
||||
if (clip) {
|
||||
cairo_clip_path_t *path = clip->path;
|
||||
|
@ -3590,6 +3629,10 @@ _cairo_dwrite_manual_show_glyphs_on_d2d_surface(void *surface,
|
|||
}
|
||||
}
|
||||
|
||||
if (!dst->isDrawing) {
|
||||
_cairo_d2d_flush_dependent_surfaces(dst);
|
||||
}
|
||||
|
||||
_cairo_d2d_set_clip(dst, NULL);
|
||||
dst->rt->Flush();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче