0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.0.1369: MS-Windows: drawing underline slow, mFallbackDC not updated

Problem:    MS-Windows: drawing underline, curl and strike-throw is slow,
            mFallbackDC not properly updated.
Solution:   Several performance improvements. (Ken Takata, Taro Muraoka,
            Yasuhiro Matsumoto, closes #2401)
This commit is contained in:
Bram Moolenaar 2017-12-05 13:22:16 +01:00
parent ce6179c799
commit 92467d3351
5 changed files with 393 additions and 132 deletions

View File

@ -6122,9 +6122,10 @@ A jump table for the options with a short description can be found at |Q_op|.
geom pixelGeometry int 0 - 2 (see below) geom pixelGeometry int 0 - 2 (see below)
renmode renderingMode int 0 - 6 (see below) renmode renderingMode int 0 - 6 (see below)
taamode textAntialiasMode int 0 - 3 (see below) taamode textAntialiasMode int 0 - 3 (see below)
scrlines Scroll Lines int >= 0 (see below)
See this URL for detail: See this URL for detail (except for scrlines):
http://msdn.microsoft.com/en-us/library/dd368190.aspx https://msdn.microsoft.com/en-us/library/dd368190.aspx
For geom: structure of a device pixel. For geom: structure of a device pixel.
0 - DWRITE_PIXEL_GEOMETRY_FLAT 0 - DWRITE_PIXEL_GEOMETRY_FLAT
@ -6132,7 +6133,7 @@ A jump table for the options with a short description can be found at |Q_op|.
2 - DWRITE_PIXEL_GEOMETRY_BGR 2 - DWRITE_PIXEL_GEOMETRY_BGR
See this URL for detail: See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368114.aspx https://msdn.microsoft.com/en-us/library/dd368114.aspx
For renmode: method of rendering glyphs. For renmode: method of rendering glyphs.
0 - DWRITE_RENDERING_MODE_DEFAULT 0 - DWRITE_RENDERING_MODE_DEFAULT
@ -6144,7 +6145,7 @@ A jump table for the options with a short description can be found at |Q_op|.
6 - DWRITE_RENDERING_MODE_OUTLINE 6 - DWRITE_RENDERING_MODE_OUTLINE
See this URL for detail: See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368118.aspx https://msdn.microsoft.com/en-us/library/dd368118.aspx
For taamode: antialiasing mode used for drawing text. For taamode: antialiasing mode used for drawing text.
0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
@ -6153,7 +6154,25 @@ A jump table for the options with a short description can be found at |Q_op|.
3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED
See this URL for detail: See this URL for detail:
http://msdn.microsoft.com/en-us/library/dd368170.aspx https://msdn.microsoft.com/en-us/library/dd368170.aspx
For scrlines: threshold for lines to be scrolled.
0 - Always use scrolling. (default)
1 - Use full page redrawing.
> 1 - If the lines to be scrolled is grater or equal to the
specified value, use redrawing. Otherwise use
scrolling.
If you feel scrolling a page (CTRL-F) is too slow with DirectX
renderer, try this "scrlines" option.
When set it "1", Vim uses full page redrawing instead of
scrolling. Redrawing a page is faster than scrolling a
page in some environments.
After that, when you feel scrolling lines (CTRL-Y) becomes
slow, please try "2" or greater value for this option.
It works threshold line number to switch scrolling to
redrawing. Scrolling a few lines might be faster than
redrawing a page in some environments.
Example: > Example: >
set encoding=utf-8 set encoding=utf-8
@ -6162,13 +6181,12 @@ A jump table for the options with a short description can be found at |Q_op|.
< <
If select a raster font (Courier, Terminal or FixedSys which If select a raster font (Courier, Terminal or FixedSys which
have ".fon" extension in file name) to 'guifont', it will be have ".fon" extension in file name) to 'guifont', it will be
drawn by GDI as a fallback. This fallback will cause drawn by GDI as a fallback.
significant slow down on drawing.
NOTE: It is known that some fonts and options combination NOTE: It is known that some fonts and options combination
causes trouble on drawing glyphs. causes trouble on drawing glyphs.
- 'rendmode:5' and 'renmode:6' will not work with some - 'renmode:5' and 'renmode:6' will not work with some
special made fonts (True-Type fonts which includes only special made fonts (True-Type fonts which includes only
bitmap glyphs). bitmap glyphs).
- 'taamode:3' will not work with some vector fonts. - 'taamode:3' will not work with some vector fonts.

View File

@ -263,14 +263,24 @@ private:
} }
}; };
enum DrawingMode {
DM_GDI = 0,
DM_DIRECTX = 1,
DM_INTEROP = 2,
};
struct DWriteContext { struct DWriteContext {
HDC mHDC; HDC mHDC;
RECT mBindRect;
DrawingMode mDMode;
HDC mInteropHDC;
bool mDrawing; bool mDrawing;
bool mFallbackDC; bool mFallbackDC;
ID2D1Factory *mD2D1Factory; ID2D1Factory *mD2D1Factory;
ID2D1DCRenderTarget *mRT; ID2D1DCRenderTarget *mRT;
ID2D1GdiInteropRenderTarget *mGDIRT;
ID2D1SolidColorBrush *mBrush; ID2D1SolidColorBrush *mBrush;
IDWriteFactory *mDWriteFactory; IDWriteFactory *mDWriteFactory;
@ -292,6 +302,10 @@ struct DWriteContext {
virtual ~DWriteContext(); virtual ~DWriteContext();
HRESULT CreateDeviceResources();
void DiscardDeviceResources();
HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat); IDWriteTextFormat **ppTextFormat);
@ -299,17 +313,21 @@ struct DWriteContext {
void SetFont(HFONT hFont); void SetFont(HFONT hFont);
void BindDC(HDC hdc, RECT *rect); void BindDC(HDC hdc, const RECT *rect);
void AssureDrawing(); HRESULT SetDrawingMode(DrawingMode mode);
ID2D1Brush* SolidBrush(COLORREF color); ID2D1Brush* SolidBrush(COLORREF color);
void DrawText(const WCHAR* text, int len, void DrawText(const WCHAR *text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color, int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx); UINT fuOptions, const RECT *lprc, const INT *lpDx);
void FillRect(RECT *rc, COLORREF color); void FillRect(const RECT *rc, COLORREF color);
void DrawLine(int x1, int y1, int x2, int y2, COLORREF color);
void SetPixel(int x, int y, COLORREF color);
void Flush(); void Flush();
@ -561,10 +579,14 @@ private:
DWriteContext::DWriteContext() : DWriteContext::DWriteContext() :
mHDC(NULL), mHDC(NULL),
mBindRect(),
mDMode(DM_GDI),
mInteropHDC(NULL),
mDrawing(false), mDrawing(false),
mFallbackDC(false), mFallbackDC(false),
mD2D1Factory(NULL), mD2D1Factory(NULL),
mRT(NULL), mRT(NULL),
mGDIRT(NULL),
mBrush(NULL), mBrush(NULL),
mDWriteFactory(NULL), mDWriteFactory(NULL),
mDWriteFactory2(NULL), mDWriteFactory2(NULL),
@ -584,25 +606,7 @@ DWriteContext::DWriteContext() :
_RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ hr = CreateDeviceResources();
D2D1_RENDER_TARGET_PROPERTIES props = {
D2D1_RENDER_TARGET_TYPE_DEFAULT,
{ DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
0, 0,
D2D1_RENDER_TARGET_USAGE_NONE,
D2D1_FEATURE_LEVEL_DEFAULT
};
hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT);
_RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT);
}
if (SUCCEEDED(hr))
{
hr = mRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&mBrush);
_RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush);
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -645,10 +649,66 @@ DWriteContext::~DWriteContext()
SafeRelease(&mDWriteFactory); SafeRelease(&mDWriteFactory);
SafeRelease(&mDWriteFactory2); SafeRelease(&mDWriteFactory2);
SafeRelease(&mBrush); SafeRelease(&mBrush);
SafeRelease(&mGDIRT);
SafeRelease(&mRT); SafeRelease(&mRT);
SafeRelease(&mD2D1Factory); SafeRelease(&mD2D1Factory);
} }
HRESULT
DWriteContext::CreateDeviceResources()
{
HRESULT hr;
if (mRT != NULL)
return S_OK;
D2D1_RENDER_TARGET_PROPERTIES props = {
D2D1_RENDER_TARGET_TYPE_DEFAULT,
{ DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
0, 0,
D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,
D2D1_FEATURE_LEVEL_DEFAULT
};
hr = mD2D1Factory->CreateDCRenderTarget(&props, &mRT);
_RPT2(_CRT_WARN, "CreateDCRenderTarget: hr=%p p=%p\n", hr, mRT);
if (SUCCEEDED(hr))
{
// This always succeeds.
mRT->QueryInterface(
__uuidof(ID2D1GdiInteropRenderTarget),
reinterpret_cast<void**>(&mGDIRT));
_RPT1(_CRT_WARN, "GdiInteropRenderTarget: p=%p\n", mGDIRT);
}
if (SUCCEEDED(hr))
{
hr = mRT->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&mBrush);
_RPT2(_CRT_WARN, "CreateSolidColorBrush: hr=%p p=%p\n", hr, mBrush);
}
if (SUCCEEDED(hr))
{
if (mHDC != NULL)
{
mRT->BindDC(mHDC, &mBindRect);
mRT->SetTransform(D2D1::IdentityMatrix());
}
}
return hr;
}
void
DWriteContext::DiscardDeviceResources()
{
SafeRelease(&mBrush);
SafeRelease(&mGDIRT);
SafeRelease(&mRT);
}
HRESULT HRESULT
DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont,
IDWriteTextFormat **ppTextFormat) IDWriteTextFormat **ppTextFormat)
@ -817,27 +877,77 @@ DWriteContext::SetFont(HFONT hFont)
item.pTextFormat = mTextFormat; item.pTextFormat = mTextFormat;
item.fontWeight = mFontWeight; item.fontWeight = mFontWeight;
item.fontStyle = mFontStyle; item.fontStyle = mFontStyle;
mFallbackDC = false;
} }
else
mFallbackDC = true;
mFontCache.put(item); mFontCache.put(item);
} }
void void
DWriteContext::BindDC(HDC hdc, RECT *rect) DWriteContext::BindDC(HDC hdc, const RECT *rect)
{ {
Flush(); Flush();
mRT->BindDC(hdc, rect); mRT->BindDC(hdc, rect);
mRT->SetTransform(D2D1::IdentityMatrix()); mRT->SetTransform(D2D1::IdentityMatrix());
mHDC = hdc; mHDC = hdc;
mBindRect = *rect;
} }
void HRESULT
DWriteContext::AssureDrawing() DWriteContext::SetDrawingMode(DrawingMode mode)
{ {
if (mDrawing == false) HRESULT hr = S_OK;
switch (mode)
{ {
mRT->BeginDraw(); default:
mDrawing = true; case DM_GDI:
if (mInteropHDC != NULL)
{
mGDIRT->ReleaseDC(NULL);
mInteropHDC = NULL;
}
if (mDrawing)
{
hr = mRT->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
{
hr = S_OK;
DiscardDeviceResources();
CreateDeviceResources();
}
mDrawing = false;
}
break;
case DM_DIRECTX:
if (mInteropHDC != NULL)
{
mGDIRT->ReleaseDC(NULL);
mInteropHDC = NULL;
}
else if (mDrawing == false)
{
CreateDeviceResources();
mRT->BeginDraw();
mDrawing = true;
}
break;
case DM_INTEROP:
if (mDrawing == false)
{
CreateDeviceResources();
mRT->BeginDraw();
mDrawing = true;
}
if (mInteropHDC == NULL)
hr = mGDIRT->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, &mInteropHDC);
break;
} }
mDMode = mode;
return hr;
} }
ID2D1Brush* ID2D1Brush*
@ -849,22 +959,31 @@ DWriteContext::SolidBrush(COLORREF color)
} }
void void
DWriteContext::DrawText(const WCHAR* text, int len, DWriteContext::DrawText(const WCHAR *text, int len,
int x, int y, int w, int h, int cellWidth, COLORREF color, int x, int y, int w, int h, int cellWidth, COLORREF color,
UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx) UINT fuOptions, const RECT *lprc, const INT *lpDx)
{ {
if (mFallbackDC) if (mFallbackDC)
{ {
Flush(); // Fall back to GDI rendering.
ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx); HRESULT hr = SetDrawingMode(DM_INTEROP);
if (SUCCEEDED(hr))
{
HGDIOBJ hFont = ::GetCurrentObject(mHDC, OBJ_FONT);
HGDIOBJ hOldFont = ::SelectObject(mInteropHDC, hFont);
::SetTextColor(mInteropHDC, color);
::SetBkMode(mInteropHDC, ::GetBkMode(mHDC));
::ExtTextOutW(mInteropHDC, x, y, fuOptions, lprc, text, len, lpDx);
::SelectObject(mInteropHDC, hOldFont);
}
return; return;
} }
AssureDrawing();
HRESULT hr; HRESULT hr;
IDWriteTextLayout *textLayout = NULL; IDWriteTextLayout *textLayout = NULL;
SetDrawingMode(DM_DIRECTX);
hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat, hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat,
FLOAT(w), FLOAT(h), &textLayout); FLOAT(w), FLOAT(h), &textLayout);
@ -883,23 +1002,74 @@ DWriteContext::DrawText(const WCHAR* text, int len,
} }
void void
DWriteContext::FillRect(RECT *rc, COLORREF color) DWriteContext::FillRect(const RECT *rc, COLORREF color)
{ {
AssureDrawing(); if (mDMode == DM_INTEROP)
mRT->FillRectangle( {
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top), // GDI functions are used before this call. Keep using GDI.
FLOAT(rc->right), FLOAT(rc->bottom)), // (Switching to Direct2D causes terrible slowdown.)
SolidBrush(color)); HBRUSH hbr = ::CreateSolidBrush(color);
::FillRect(mInteropHDC, rc, hbr);
::DeleteObject(HGDIOBJ(hbr));
}
else
{
SetDrawingMode(DM_DIRECTX);
mRT->FillRectangle(
D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top),
FLOAT(rc->right), FLOAT(rc->bottom)),
SolidBrush(color));
}
}
void
DWriteContext::DrawLine(int x1, int y1, int x2, int y2, COLORREF color)
{
if (mDMode == DM_INTEROP)
{
// GDI functions are used before this call. Keep using GDI.
// (Switching to Direct2D causes terrible slowdown.)
HPEN hpen = ::CreatePen(PS_SOLID, 1, color);
HGDIOBJ old_pen = ::SelectObject(mInteropHDC, HGDIOBJ(hpen));
::MoveToEx(mInteropHDC, x1, y1, NULL);
::LineTo(mInteropHDC, x2, y2);
::SelectObject(mInteropHDC, old_pen);
::DeleteObject(HGDIOBJ(hpen));
}
else
{
SetDrawingMode(DM_DIRECTX);
mRT->DrawLine(
D2D1::Point2F(FLOAT(x1), FLOAT(y1) + 0.5f),
D2D1::Point2F(FLOAT(x2), FLOAT(y2) + 0.5f),
SolidBrush(color));
}
}
void
DWriteContext::SetPixel(int x, int y, COLORREF color)
{
if (mDMode == DM_INTEROP)
{
// GDI functions are used before this call. Keep using GDI.
// (Switching to Direct2D causes terrible slowdown.)
::SetPixel(mInteropHDC, x, y, color);
}
else
{
SetDrawingMode(DM_DIRECTX);
// Direct2D doesn't have SetPixel API. Use DrawLine instead.
mRT->DrawLine(
D2D1::Point2F(FLOAT(x), FLOAT(y) + 0.5f),
D2D1::Point2F(FLOAT(x+1), FLOAT(y) + 0.5f),
SolidBrush(color));
}
} }
void void
DWriteContext::Flush() DWriteContext::Flush()
{ {
if (mDrawing) SetDrawingMode(DM_GDI);
{
mRT->EndDraw();
mDrawing = false;
}
} }
void void
@ -1000,7 +1170,7 @@ DWriteContext_Open(void)
} }
void void
DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect) DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect)
{ {
if (ctx != NULL) if (ctx != NULL)
ctx->BindDC(hdc, rect); ctx->BindDC(hdc, rect);
@ -1016,7 +1186,7 @@ DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont)
void void
DWriteContext_DrawText( DWriteContext_DrawText(
DWriteContext *ctx, DWriteContext *ctx,
const WCHAR* text, const WCHAR *text,
int len, int len,
int x, int x,
int y, int y,
@ -1025,8 +1195,8 @@ DWriteContext_DrawText(
int cellWidth, int cellWidth,
COLORREF color, COLORREF color,
UINT fuOptions, UINT fuOptions,
CONST RECT *lprc, const RECT *lprc,
CONST INT * lpDx) const INT *lpDx)
{ {
if (ctx != NULL) if (ctx != NULL)
ctx->DrawText(text, len, x, y, w, h, cellWidth, color, ctx->DrawText(text, len, x, y, w, h, cellWidth, color,
@ -1034,12 +1204,27 @@ DWriteContext_DrawText(
} }
void void
DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color) DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color)
{ {
if (ctx != NULL) if (ctx != NULL)
ctx->FillRect(rc, color); ctx->FillRect(rc, color);
} }
void
DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2,
COLORREF color)
{
if (ctx != NULL)
ctx->DrawLine(x1, y1, x2, y2, color);
}
void
DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color)
{
if (ctx != NULL)
ctx->SetPixel(x, y, color);
}
void void
DWriteContext_Flush(DWriteContext *ctx) DWriteContext_Flush(DWriteContext *ctx)
{ {

View File

@ -55,11 +55,11 @@ void DWrite_Init(void);
void DWrite_Final(void); void DWrite_Final(void);
DWriteContext *DWriteContext_Open(void); DWriteContext *DWriteContext_Open(void);
void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect); void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect);
void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont);
void DWriteContext_DrawText( void DWriteContext_DrawText(
DWriteContext *ctx, DWriteContext *ctx,
const WCHAR* text, const WCHAR *text,
int len, int len,
int x, int x,
int y, int y,
@ -68,9 +68,12 @@ void DWriteContext_DrawText(
int cellWidth, int cellWidth,
COLORREF color, COLORREF color,
UINT fuOptions, UINT fuOptions,
CONST RECT *lprc, const RECT *lprc,
CONST INT * lpDx); const INT *lpDx);
void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color); void DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color);
void DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2,
COLORREF color);
void DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color);
void DWriteContext_Flush(DWriteContext *ctx); void DWriteContext_Flush(DWriteContext *ctx);
void DWriteContext_Close(DWriteContext *ctx); void DWriteContext_Close(DWriteContext *ctx);

View File

@ -33,6 +33,7 @@
static DWriteContext *s_dwc = NULL; static DWriteContext *s_dwc = NULL;
static int s_directx_enabled = 0; static int s_directx_enabled = 0;
static int s_directx_load_attempted = 0; static int s_directx_load_attempted = 0;
static int s_directx_scrlines = 0;
# define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL) # define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL)
static int directx_enabled(void); static int directx_enabled(void);
static void directx_binddc(void); static void directx_binddc(void);
@ -57,6 +58,7 @@ gui_mch_set_rendering_options(char_u *s)
int dx_geom = 0; int dx_geom = 0;
int dx_renmode = 0; int dx_renmode = 0;
int dx_taamode = 0; int dx_taamode = 0;
int dx_scrlines = 0;
/* parse string as rendering options. */ /* parse string as rendering options. */
for (p = s; p != NULL && *p != NUL; ) for (p = s; p != NULL && *p != NUL; )
@ -117,6 +119,10 @@ gui_mch_set_rendering_options(char_u *s)
if (dx_taamode < 0 || dx_taamode > 3) if (dx_taamode < 0 || dx_taamode > 3)
return FAIL; return FAIL;
} }
else if (STRCMP(name, "scrlines") == 0)
{
dx_scrlines = atoi((char *)value);
}
else else
return FAIL; return FAIL;
} }
@ -147,6 +153,7 @@ gui_mch_set_rendering_options(char_u *s)
} }
} }
s_directx_enabled = dx_enable; s_directx_enabled = dx_enable;
s_directx_scrlines = dx_scrlines;
return OK; return OK;
#else #else
@ -283,6 +290,7 @@ typedef int UINT_PTR;
#endif #endif
static void _OnPaint( HWND hwnd); static void _OnPaint( HWND hwnd);
static void fill_rect(const RECT *rcp, HBRUSH hbr, COLORREF color);
static void clear_rect(RECT *rcp); static void clear_rect(RECT *rcp);
static WORD s_dlgfntheight; /* height of the dialog font */ static WORD s_dlgfntheight; /* height of the dialog font */
@ -605,10 +613,7 @@ _OnBlinkTimer(
blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime,
(TIMERPROC)_OnBlinkTimer); (TIMERPROC)_OnBlinkTimer);
} }
#if defined(FEAT_DIRECTX) gui_mch_flush();
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
} }
static void static void
@ -634,7 +639,10 @@ gui_mch_stop_blink(void)
{ {
gui_mswin_rm_blink_timer(); gui_mswin_rm_blink_timer();
if (blink_state == BLINK_OFF) if (blink_state == BLINK_OFF)
{
gui_update_cursor(TRUE, FALSE); gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
}
blink_state = BLINK_NONE; blink_state = BLINK_NONE;
} }
@ -654,6 +662,7 @@ gui_mch_start_blink(void)
(TIMERPROC)_OnBlinkTimer); (TIMERPROC)_OnBlinkTimer);
blink_state = BLINK_ON; blink_state = BLINK_ON;
gui_update_cursor(TRUE, FALSE); gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
} }
} }
@ -1730,7 +1739,6 @@ gui_mch_draw_part_cursor(
int h, int h,
guicolor_T color) guicolor_T color)
{ {
HBRUSH hbr;
RECT rc; RECT rc;
/* /*
@ -1746,14 +1754,7 @@ gui_mch_draw_part_cursor(
rc.right = rc.left + w; rc.right = rc.left + w;
rc.bottom = rc.top + h; rc.bottom = rc.top + h;
#if defined(FEAT_DIRECTX) fill_rect(&rc, NULL, color);
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif
hbr = CreateSolidBrush(color);
FillRect(s_hdc, &rc, hbr);
DeleteBrush(hbr);
} }
@ -3122,13 +3123,8 @@ gui_mch_delete_lines(
int num_lines) int num_lines)
{ {
RECT rc; RECT rc;
intel_gpu_workaround();
#if defined(FEAT_DIRECTX) #if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx. int use_redraw = 0;
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif #endif
rc.left = FILL_X(gui.scroll_region_left); rc.left = FILL_X(gui.scroll_region_left);
@ -3136,8 +3132,24 @@ gui_mch_delete_lines(
rc.top = FILL_Y(row); rc.top = FILL_Y(row);
rc.bottom = FILL_Y(gui.scroll_region_bot + 1); rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, #if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
use_redraw = 1;
}
else
DWriteContext_Flush(s_dwc);
}
if (!use_redraw)
#endif
{
intel_gpu_workaround();
ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags()); &rc, &rc, NULL, NULL, get_scroll_flags());
}
UpdateWindow(s_textArea); UpdateWindow(s_textArea);
/* This seems to be required to avoid the cursor disappearing when /* This seems to be required to avoid the cursor disappearing when
@ -3161,23 +3173,35 @@ gui_mch_insert_lines(
int num_lines) int num_lines)
{ {
RECT rc; RECT rc;
intel_gpu_workaround();
#if defined(FEAT_DIRECTX) #if defined(FEAT_DIRECTX)
// Commit drawing queue before ScrollWindowEx. int use_redraw = 0;
if (IS_ENABLE_DIRECTX())
DWriteContext_Flush(s_dwc);
#endif #endif
rc.left = FILL_X(gui.scroll_region_left); rc.left = FILL_X(gui.scroll_region_left);
rc.right = FILL_X(gui.scroll_region_right + 1); rc.right = FILL_X(gui.scroll_region_right + 1);
rc.top = FILL_Y(row); rc.top = FILL_Y(row);
rc.bottom = FILL_Y(gui.scroll_region_bot + 1); rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
/* The SW_INVALIDATE is required when part of the window is covered or
* off-screen. How do we avoid it when it's not needed? */ #if defined(FEAT_DIRECTX)
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, if (IS_ENABLE_DIRECTX())
{
if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines)
{
RedrawWindow(s_textArea, &rc, NULL, RDW_INVALIDATE);
use_redraw = 1;
}
else
DWriteContext_Flush(s_dwc);
}
if (!use_redraw)
#endif
{
intel_gpu_workaround();
/* The SW_INVALIDATE is required when part of the window is covered or
* off-screen. How do we avoid it when it's not needed? */
ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height,
&rc, &rc, NULL, NULL, get_scroll_flags()); &rc, &rc, NULL, NULL, get_scroll_flags());
}
UpdateWindow(s_textArea); UpdateWindow(s_textArea);
@ -5853,6 +5877,7 @@ _OnImeNotify(HWND hWnd, DWORD dwCommand, DWORD dwData UNUSED)
} }
} }
gui_update_cursor(TRUE, FALSE); gui_update_cursor(TRUE, FALSE);
gui_mch_flush();
lResult = 0; lResult = 0;
break; break;
} }
@ -6181,6 +6206,67 @@ RevOut( HDC s_hdc,
} }
#endif #endif
static void
draw_line(
int x1,
int y1,
int x2,
int y2,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_DrawLine(s_dwc, x1, y1, x2, y2, color);
else
#endif
{
HPEN hpen = CreatePen(PS_SOLID, 1, color);
HPEN old_pen = SelectObject(s_hdc, hpen);
MoveToEx(s_hdc, x1, y1, NULL);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, x2, y2);
DeleteObject(SelectObject(s_hdc, old_pen));
}
}
static void
set_pixel(
int x,
int y,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_SetPixel(s_dwc, x, y, color);
else
#endif
SetPixel(s_hdc, x, y, color);
}
static void
fill_rect(
const RECT *rcp,
HBRUSH hbr,
COLORREF color)
{
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
DWriteContext_FillRect(s_dwc, rcp, color);
else
#endif
{
HBRUSH hbr2;
if (hbr == NULL)
hbr2 = CreateSolidBrush(color);
else
hbr2 = hbr;
FillRect(s_hdc, rcp, hbr2);
if (hbr == NULL)
DeleteBrush(hbr2);
}
}
void void
gui_mch_draw_string( gui_mch_draw_string(
int row, int row,
@ -6200,7 +6286,6 @@ gui_mch_draw_string(
static int unibuflen = 0; static int unibuflen = 0;
int n = 0; int n = 0;
#endif #endif
HPEN hpen, old_pen;
int y; int y;
/* /*
@ -6263,11 +6348,7 @@ gui_mch_draw_string(
brush_lru = !brush_lru; brush_lru = !brush_lru;
} }
#if defined(FEAT_DIRECTX) fill_rect(&rc, hbr, gui.currBgColor);
if (IS_ENABLE_DIRECTX())
DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor);
#endif
FillRect(s_hdc, &rc, hbr);
SetBkMode(s_hdc, TRANSPARENT); SetBkMode(s_hdc, TRANSPARENT);
@ -6462,38 +6543,22 @@ gui_mch_draw_string(
foptions, pcliprect, (char *)text, len, padding); foptions, pcliprect, (char *)text, len, padding);
} }
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX() &&
(flags & (DRAW_UNDERL | DRAW_STRIKE | DRAW_UNDERC | DRAW_CURSOR)))
DWriteContext_Flush(s_dwc);
#endif
/* Underline */ /* Underline */
if (flags & DRAW_UNDERL) if (flags & DRAW_UNDERL)
{ {
hpen = CreatePen(PS_SOLID, 1, gui.currFgColor);
old_pen = SelectObject(s_hdc, hpen);
/* When p_linespace is 0, overwrite the bottom row of pixels. /* When p_linespace is 0, overwrite the bottom row of pixels.
* Otherwise put the line just below the character. */ * Otherwise put the line just below the character. */
y = FILL_Y(row + 1) - 1; y = FILL_Y(row + 1) - 1;
if (p_linespace > 1) if (p_linespace > 1)
y -= p_linespace - 1; y -= p_linespace - 1;
MoveToEx(s_hdc, FILL_X(col), y, NULL); draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currFgColor);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, FILL_X(col + len), y);
DeleteObject(SelectObject(s_hdc, old_pen));
} }
/* Strikethrough */ /* Strikethrough */
if (flags & DRAW_STRIKE) if (flags & DRAW_STRIKE)
{ {
hpen = CreatePen(PS_SOLID, 1, gui.currSpColor);
old_pen = SelectObject(s_hdc, hpen);
y = FILL_Y(row + 1) - gui.char_height/2; y = FILL_Y(row + 1) - gui.char_height/2;
MoveToEx(s_hdc, FILL_X(col), y, NULL); draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currSpColor);
/* Note: LineTo() excludes the last pixel in the line. */
LineTo(s_hdc, FILL_X(col + len), y);
DeleteObject(SelectObject(s_hdc, old_pen));
} }
/* Undercurl */ /* Undercurl */
@ -6507,7 +6572,7 @@ gui_mch_draw_string(
for (x = FILL_X(col); x < FILL_X(col + len); ++x) for (x = FILL_X(col); x < FILL_X(col + len); ++x)
{ {
offset = val[x % 8]; offset = val[x % 8];
SetPixel(s_hdc, x, y - offset, gui.currSpColor); set_pixel(x, y - offset, gui.currSpColor);
} }
} }
} }
@ -6541,19 +6606,7 @@ gui_mch_flush(void)
static void static void
clear_rect(RECT *rcp) clear_rect(RECT *rcp)
{ {
HBRUSH hbr; fill_rect(rcp, NULL, gui.back_pixel);
#if defined(FEAT_DIRECTX)
if (IS_ENABLE_DIRECTX())
{
DWriteContext_FillRect(s_dwc, rcp, gui.back_pixel);
return;
}
#endif
hbr = CreateSolidBrush(gui.back_pixel);
FillRect(s_hdc, rcp, hbr);
DeleteBrush(hbr);
} }

View File

@ -771,6 +771,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1369,
/**/ /**/
1368, 1368,
/**/ /**/