зеркало из 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-win32-refptr.h"
|
||||||
#include "cairo-d2d-private-fx.h"
|
#include "cairo-d2d-private-fx.h"
|
||||||
#include "cairo-win32.h"
|
#include "cairo-win32.h"
|
||||||
|
#include "cairo-list-private.h"
|
||||||
|
|
||||||
/* describes the type of the currently applied clip so that we can pop it */
|
/* describes the type of the currently applied clip so that we can pop it */
|
||||||
struct d2d_clip;
|
struct d2d_clip;
|
||||||
|
@ -81,7 +82,11 @@ struct _cairo_d2d_surface {
|
||||||
textRenderingState(TEXT_RENDERING_UNINITIALIZED)
|
textRenderingState(TEXT_RENDERING_UNINITIALIZED)
|
||||||
{
|
{
|
||||||
_cairo_clip_init (&this->clip);
|
_cairo_clip_init (&this->clip);
|
||||||
|
cairo_list_init(&this->dependent_surfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~_cairo_d2d_surface();
|
||||||
|
|
||||||
|
|
||||||
cairo_surface_t base;
|
cairo_surface_t base;
|
||||||
/* Device used by this surface
|
/* Device used by this surface
|
||||||
|
@ -139,11 +144,23 @@ struct _cairo_d2d_surface {
|
||||||
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
|
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
|
||||||
RefPtr<ID3D10ShaderResourceView> buffer_sr_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;
|
//cairo_surface_clipper_t clipper;
|
||||||
};
|
};
|
||||||
typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
|
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)(
|
typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
|
||||||
__in D2D1_FACTORY_TYPE factoryType,
|
__in D2D1_FACTORY_TYPE factoryType,
|
||||||
__in REFIID iid,
|
__in REFIID iid,
|
||||||
|
|
|
@ -1053,6 +1053,25 @@ _cairo_d2d_set_clip (cairo_d2d_surface_t *d2dsurf, cairo_clip_t *clip)
|
||||||
return CAIRO_STATUS_SUCCESS;
|
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
|
* 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.
|
* 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)
|
static void _begin_draw_state(cairo_d2d_surface_t* surface)
|
||||||
{
|
{
|
||||||
if (!surface->isDrawing) {
|
if (!surface->isDrawing) {
|
||||||
|
_cairo_d2d_flush_dependent_surfaces(surface);
|
||||||
surface->rt->BeginDraw();
|
surface->rt->BeginDraw();
|
||||||
surface->isDrawing = true;
|
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_update_surface_bitmap(srcSurf);
|
||||||
_cairo_d2d_flush(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) {
|
if (pattern->extend == CAIRO_EXTEND_NONE) {
|
||||||
ID2D1Bitmap *srcSurfBitmap = srcSurf->surfaceBitmap;
|
ID2D1Bitmap *srcSurfBitmap = srcSurf->surfaceBitmap;
|
||||||
d2dsurf->rt->CreateBitmap(
|
d2dsurf->rt->CreateBitmap(
|
||||||
|
@ -2327,6 +2350,18 @@ _cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_de
|
||||||
cairo_addref_device(&d2d_device->base);
|
cairo_addref_device(&d2d_device->base);
|
||||||
d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
|
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
|
// Implementation
|
||||||
static cairo_surface_t*
|
static cairo_surface_t*
|
||||||
|
@ -2793,6 +2828,8 @@ _cairo_d2d_blend_surface(cairo_d2d_surface_t *dst,
|
||||||
needsTransform = true;
|
needsTransform = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cairo_d2d_add_dependent_surface(src, dst);
|
||||||
|
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE interpMode =
|
D2D1_BITMAP_INTERPOLATION_MODE interpMode =
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR;
|
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
|
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_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;
|
int numPaths = 0;
|
||||||
if (clip) {
|
if (clip) {
|
||||||
cairo_clip_path_t *path = clip->path;
|
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);
|
_cairo_d2d_set_clip(dst, NULL);
|
||||||
dst->rt->Flush();
|
dst->rt->Flush();
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче