To: vim_dev@googlegroups.com Subject: Patch 8.0.1369 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1369 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) Files: runtime/doc/options.txt, src/gui_dwrite.cpp, src/gui_dwrite.h, src/gui_w32.c *** ../vim-8.0.1368/runtime/doc/options.txt 2017-12-01 20:35:54.864077110 +0100 --- runtime/doc/options.txt 2017-12-05 13:18:55.511425089 +0100 *************** *** 6017,6025 **** geom pixelGeometry int 0 - 2 (see below) renmode renderingMode int 0 - 6 (see below) taamode textAntialiasMode int 0 - 3 (see below) ! See this URL for detail: ! http://msdn.microsoft.com/en-us/library/dd368190.aspx For geom: structure of a device pixel. 0 - DWRITE_PIXEL_GEOMETRY_FLAT --- 6122,6131 ---- geom pixelGeometry int 0 - 2 (see below) renmode renderingMode int 0 - 6 (see below) taamode textAntialiasMode int 0 - 3 (see below) + scrlines Scroll Lines int >= 0 (see below) ! See this URL for detail (except for scrlines): ! https://msdn.microsoft.com/en-us/library/dd368190.aspx For geom: structure of a device pixel. 0 - DWRITE_PIXEL_GEOMETRY_FLAT *************** *** 6027,6033 **** 2 - DWRITE_PIXEL_GEOMETRY_BGR See this URL for detail: ! http://msdn.microsoft.com/en-us/library/dd368114.aspx For renmode: method of rendering glyphs. 0 - DWRITE_RENDERING_MODE_DEFAULT --- 6133,6139 ---- 2 - DWRITE_PIXEL_GEOMETRY_BGR See this URL for detail: ! https://msdn.microsoft.com/en-us/library/dd368114.aspx For renmode: method of rendering glyphs. 0 - DWRITE_RENDERING_MODE_DEFAULT *************** *** 6039,6045 **** 6 - DWRITE_RENDERING_MODE_OUTLINE See this URL for detail: ! http://msdn.microsoft.com/en-us/library/dd368118.aspx For taamode: antialiasing mode used for drawing text. 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT --- 6145,6151 ---- 6 - DWRITE_RENDERING_MODE_OUTLINE See this URL for detail: ! https://msdn.microsoft.com/en-us/library/dd368118.aspx For taamode: antialiasing mode used for drawing text. 0 - D2D1_TEXT_ANTIALIAS_MODE_DEFAULT *************** *** 6048,6054 **** 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED See this URL for detail: ! http://msdn.microsoft.com/en-us/library/dd368170.aspx Example: > set encoding=utf-8 --- 6154,6178 ---- 3 - D2D1_TEXT_ANTIALIAS_MODE_ALIASED See this URL for detail: ! 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: > set encoding=utf-8 *************** *** 6057,6069 **** < If select a raster font (Courier, Terminal or FixedSys which have ".fon" extension in file name) to 'guifont', it will be ! drawn by GDI as a fallback. This fallback will cause ! significant slow down on drawing. NOTE: It is known that some fonts and options combination causes trouble on drawing glyphs. ! - 'rendmode:5' and 'renmode:6' will not work with some special made fonts (True-Type fonts which includes only bitmap glyphs). - 'taamode:3' will not work with some vector fonts. --- 6181,6192 ---- < If select a raster font (Courier, Terminal or FixedSys which have ".fon" extension in file name) to 'guifont', it will be ! drawn by GDI as a fallback. NOTE: It is known that some fonts and options combination causes trouble on drawing glyphs. ! - 'renmode:5' and 'renmode:6' will not work with some special made fonts (True-Type fonts which includes only bitmap glyphs). - 'taamode:3' will not work with some vector fonts. *** ../vim-8.0.1368/src/gui_dwrite.cpp 2017-11-26 14:29:24.847931598 +0100 --- src/gui_dwrite.cpp 2017-12-05 13:18:55.511425089 +0100 *************** *** 263,276 **** --- 263,286 ---- } }; + enum DrawingMode { + DM_GDI = 0, + DM_DIRECTX = 1, + DM_INTEROP = 2, + }; + struct DWriteContext { HDC mHDC; + RECT mBindRect; + DrawingMode mDMode; + HDC mInteropHDC; bool mDrawing; bool mFallbackDC; ID2D1Factory *mD2D1Factory; ID2D1DCRenderTarget *mRT; + ID2D1GdiInteropRenderTarget *mGDIRT; ID2D1SolidColorBrush *mBrush; IDWriteFactory *mDWriteFactory; *************** *** 292,297 **** --- 302,311 ---- virtual ~DWriteContext(); + HRESULT CreateDeviceResources(); + + void DiscardDeviceResources(); + HRESULT CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, IDWriteTextFormat **ppTextFormat); *************** *** 299,315 **** void SetFont(HFONT hFont); ! void BindDC(HDC hdc, RECT *rect); ! void AssureDrawing(); ID2D1Brush* SolidBrush(COLORREF color); ! void DrawText(const WCHAR* text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, ! UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx); ! void FillRect(RECT *rc, COLORREF color); void Flush(); --- 313,333 ---- void SetFont(HFONT hFont); ! void BindDC(HDC hdc, const RECT *rect); ! HRESULT SetDrawingMode(DrawingMode mode); ID2D1Brush* SolidBrush(COLORREF color); ! void DrawText(const WCHAR *text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, ! UINT fuOptions, const RECT *lprc, const INT *lpDx); ! 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(); *************** *** 561,570 **** --- 579,592 ---- DWriteContext::DWriteContext() : mHDC(NULL), + mBindRect(), + mDMode(DM_GDI), + mInteropHDC(NULL), mDrawing(false), mFallbackDC(false), mD2D1Factory(NULL), mRT(NULL), + mGDIRT(NULL), mBrush(NULL), mDWriteFactory(NULL), mDWriteFactory2(NULL), *************** *** 584,608 **** _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); if (SUCCEEDED(hr)) ! { ! 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)) { --- 606,612 ---- _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); if (SUCCEEDED(hr)) ! hr = CreateDeviceResources(); if (SUCCEEDED(hr)) { *************** *** 645,655 **** --- 649,715 ---- SafeRelease(&mDWriteFactory); SafeRelease(&mDWriteFactory2); SafeRelease(&mBrush); + SafeRelease(&mGDIRT); SafeRelease(&mRT); 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(&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 DWriteContext::CreateTextFormatFromLOGFONT(const LOGFONTW &logFont, IDWriteTextFormat **ppTextFormat) { *************** *** 817,843 **** item.pTextFormat = mTextFormat; item.fontWeight = mFontWeight; item.fontStyle = mFontStyle; } mFontCache.put(item); } void ! DWriteContext::BindDC(HDC hdc, RECT *rect) { Flush(); mRT->BindDC(hdc, rect); mRT->SetTransform(D2D1::IdentityMatrix()); mHDC = hdc; } ! void ! DWriteContext::AssureDrawing() { ! if (mDrawing == false) { ! mRT->BeginDraw(); ! mDrawing = true; } } ID2D1Brush* --- 877,953 ---- item.pTextFormat = mTextFormat; item.fontWeight = mFontWeight; item.fontStyle = mFontStyle; + mFallbackDC = false; } + else + mFallbackDC = true; mFontCache.put(item); } void ! DWriteContext::BindDC(HDC hdc, const RECT *rect) { Flush(); mRT->BindDC(hdc, rect); mRT->SetTransform(D2D1::IdentityMatrix()); mHDC = hdc; + mBindRect = *rect; } ! HRESULT ! DWriteContext::SetDrawingMode(DrawingMode mode) { ! HRESULT hr = S_OK; ! ! switch (mode) { ! default: ! 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* *************** *** 849,870 **** } void ! DWriteContext::DrawText(const WCHAR* text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, ! UINT fuOptions, CONST RECT *lprc, CONST INT * lpDx) { if (mFallbackDC) { ! Flush(); ! ExtTextOutW(mHDC, x, y, fuOptions, lprc, text, len, lpDx); return; } - AssureDrawing(); - HRESULT hr; IDWriteTextLayout *textLayout = NULL; hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat, FLOAT(w), FLOAT(h), &textLayout); --- 959,989 ---- } void ! DWriteContext::DrawText(const WCHAR *text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color, ! UINT fuOptions, const RECT *lprc, const INT *lpDx) { if (mFallbackDC) { ! // Fall back to GDI rendering. ! 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; } HRESULT hr; IDWriteTextLayout *textLayout = NULL; + SetDrawingMode(DM_DIRECTX); + hr = mDWriteFactory->CreateTextLayout(text, len, mTextFormat, FLOAT(w), FLOAT(h), &textLayout); *************** *** 883,908 **** } void ! DWriteContext::FillRect(RECT *rc, COLORREF color) { ! AssureDrawing(); ! mRT->FillRectangle( ! D2D1::RectF(FLOAT(rc->left), FLOAT(rc->top), ! FLOAT(rc->right), FLOAT(rc->bottom)), ! SolidBrush(color)); } void ! DWriteContext::Flush() { ! if (mDrawing) { ! mRT->EndDraw(); ! mDrawing = false; } } void DWriteContext::SetRenderingParams( const DWriteRenderingParams *params) { --- 1002,1078 ---- } void ! DWriteContext::FillRect(const RECT *rc, COLORREF color) { ! if (mDMode == DM_INTEROP) ! { ! // GDI functions are used before this call. Keep using GDI. ! // (Switching to Direct2D causes terrible slowdown.) ! 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 + DWriteContext::Flush() + { + SetDrawingMode(DM_GDI); + } + + void DWriteContext::SetRenderingParams( const DWriteRenderingParams *params) { *************** *** 1000,1006 **** } void ! DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect) { if (ctx != NULL) ctx->BindDC(hdc, rect); --- 1170,1176 ---- } void ! DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect) { if (ctx != NULL) ctx->BindDC(hdc, rect); *************** *** 1016,1022 **** void DWriteContext_DrawText( DWriteContext *ctx, ! const WCHAR* text, int len, int x, int y, --- 1186,1192 ---- void DWriteContext_DrawText( DWriteContext *ctx, ! const WCHAR *text, int len, int x, int y, *************** *** 1025,1032 **** int cellWidth, COLORREF color, UINT fuOptions, ! CONST RECT *lprc, ! CONST INT * lpDx) { if (ctx != NULL) ctx->DrawText(text, len, x, y, w, h, cellWidth, color, --- 1195,1202 ---- int cellWidth, COLORREF color, UINT fuOptions, ! const RECT *lprc, ! const INT *lpDx) { if (ctx != NULL) ctx->DrawText(text, len, x, y, w, h, cellWidth, color, *************** *** 1034,1046 **** } void ! DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color) { if (ctx != NULL) ctx->FillRect(rc, color); } void DWriteContext_Flush(DWriteContext *ctx) { if (ctx != NULL) --- 1204,1231 ---- } void ! DWriteContext_FillRect(DWriteContext *ctx, const RECT *rc, COLORREF color) { if (ctx != NULL) 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 DWriteContext_Flush(DWriteContext *ctx) { if (ctx != NULL) *** ../vim-8.0.1368/src/gui_dwrite.h 2017-11-26 14:29:24.847931598 +0100 --- src/gui_dwrite.h 2017-12-05 13:18:55.511425089 +0100 *************** *** 55,65 **** void DWrite_Final(void); DWriteContext *DWriteContext_Open(void); ! void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, RECT *rect); void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); void DWriteContext_DrawText( DWriteContext *ctx, ! const WCHAR* text, int len, int x, int y, --- 55,65 ---- void DWrite_Final(void); DWriteContext *DWriteContext_Open(void); ! void DWriteContext_BindDC(DWriteContext *ctx, HDC hdc, const RECT *rect); void DWriteContext_SetFont(DWriteContext *ctx, HFONT hFont); void DWriteContext_DrawText( DWriteContext *ctx, ! const WCHAR *text, int len, int x, int y, *************** *** 68,76 **** int cellWidth, COLORREF color, UINT fuOptions, ! CONST RECT *lprc, ! CONST INT * lpDx); ! void DWriteContext_FillRect(DWriteContext *ctx, RECT *rc, COLORREF color); void DWriteContext_Flush(DWriteContext *ctx); void DWriteContext_Close(DWriteContext *ctx); --- 68,79 ---- int cellWidth, COLORREF color, UINT fuOptions, ! const RECT *lprc, ! const INT *lpDx); ! 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_Close(DWriteContext *ctx); *** ../vim-8.0.1368/src/gui_w32.c 2017-11-27 23:24:04.837331762 +0100 --- src/gui_w32.c 2017-12-05 13:18:55.511425089 +0100 *************** *** 33,38 **** --- 33,39 ---- static DWriteContext *s_dwc = NULL; static int s_directx_enabled = 0; static int s_directx_load_attempted = 0; + static int s_directx_scrlines = 0; # define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL) static int directx_enabled(void); static void directx_binddc(void); *************** *** 57,62 **** --- 58,64 ---- int dx_geom = 0; int dx_renmode = 0; int dx_taamode = 0; + int dx_scrlines = 0; /* parse string as rendering options. */ for (p = s; p != NULL && *p != NUL; ) *************** *** 117,122 **** --- 119,128 ---- if (dx_taamode < 0 || dx_taamode > 3) return FAIL; } + else if (STRCMP(name, "scrlines") == 0) + { + dx_scrlines = atoi((char *)value); + } else return FAIL; } *************** *** 147,152 **** --- 153,159 ---- } } s_directx_enabled = dx_enable; + s_directx_scrlines = dx_scrlines; return OK; #else *************** *** 283,288 **** --- 290,296 ---- #endif static void _OnPaint( HWND hwnd); + static void fill_rect(const RECT *rcp, HBRUSH hbr, COLORREF color); static void clear_rect(RECT *rcp); static WORD s_dlgfntheight; /* height of the dialog font */ *************** *** 605,614 **** blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, (TIMERPROC)_OnBlinkTimer); } ! #if defined(FEAT_DIRECTX) ! if (IS_ENABLE_DIRECTX()) ! DWriteContext_Flush(s_dwc); ! #endif } static void --- 613,619 ---- blink_timer = (UINT) SetTimer(NULL, 0, (UINT)blink_ontime, (TIMERPROC)_OnBlinkTimer); } ! gui_mch_flush(); } static void *************** *** 634,640 **** --- 639,648 ---- { gui_mswin_rm_blink_timer(); if (blink_state == BLINK_OFF) + { gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); + } blink_state = BLINK_NONE; } *************** *** 654,659 **** --- 662,668 ---- (TIMERPROC)_OnBlinkTimer); blink_state = BLINK_ON; gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); } } *************** *** 1730,1736 **** int h, guicolor_T color) { - HBRUSH hbr; RECT rc; /* --- 1739,1744 ---- *************** *** 1746,1759 **** rc.right = rc.left + w; rc.bottom = rc.top + h; ! #if defined(FEAT_DIRECTX) ! if (IS_ENABLE_DIRECTX()) ! DWriteContext_Flush(s_dwc); ! #endif ! ! hbr = CreateSolidBrush(color); ! FillRect(s_hdc, &rc, hbr); ! DeleteBrush(hbr); } --- 1754,1760 ---- rc.right = rc.left + w; rc.bottom = rc.top + h; ! fill_rect(&rc, NULL, color); } *************** *** 3122,3134 **** int num_lines) { RECT rc; - - intel_gpu_workaround(); - #if defined(FEAT_DIRECTX) ! // Commit drawing queue before ScrollWindowEx. ! if (IS_ENABLE_DIRECTX()) ! DWriteContext_Flush(s_dwc); #endif rc.left = FILL_X(gui.scroll_region_left); --- 3123,3130 ---- int num_lines) { RECT rc; #if defined(FEAT_DIRECTX) ! int use_redraw = 0; #endif rc.left = FILL_X(gui.scroll_region_left); *************** *** 3136,3143 **** rc.top = FILL_Y(row); rc.bottom = FILL_Y(gui.scroll_region_bot + 1); ! ScrollWindowEx(s_textArea, 0, -num_lines * gui.char_height, &rc, &rc, NULL, NULL, get_scroll_flags()); UpdateWindow(s_textArea); /* This seems to be required to avoid the cursor disappearing when --- 3132,3155 ---- rc.top = FILL_Y(row); rc.bottom = FILL_Y(gui.scroll_region_bot + 1); ! #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()); + } UpdateWindow(s_textArea); /* This seems to be required to avoid the cursor disappearing when *************** *** 3161,3183 **** int num_lines) { RECT rc; - - intel_gpu_workaround(); - #if defined(FEAT_DIRECTX) ! // Commit drawing queue before ScrollWindowEx. ! if (IS_ENABLE_DIRECTX()) ! DWriteContext_Flush(s_dwc); #endif rc.left = FILL_X(gui.scroll_region_left); rc.right = FILL_X(gui.scroll_region_right + 1); rc.top = FILL_Y(row); 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? */ ! ScrollWindowEx(s_textArea, 0, num_lines * gui.char_height, &rc, &rc, NULL, NULL, get_scroll_flags()); UpdateWindow(s_textArea); --- 3173,3207 ---- int num_lines) { RECT rc; #if defined(FEAT_DIRECTX) ! int use_redraw = 0; #endif rc.left = FILL_X(gui.scroll_region_left); rc.right = FILL_X(gui.scroll_region_right + 1); rc.top = FILL_Y(row); rc.bottom = FILL_Y(gui.scroll_region_bot + 1); ! ! #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(); ! /* 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()); + } UpdateWindow(s_textArea); *************** *** 5853,5858 **** --- 5877,5883 ---- } } gui_update_cursor(TRUE, FALSE); + gui_mch_flush(); lResult = 0; break; } *************** *** 6181,6186 **** --- 6206,6272 ---- } #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 gui_mch_draw_string( int row, *************** *** 6200,6206 **** static int unibuflen = 0; int n = 0; #endif - HPEN hpen, old_pen; int y; /* --- 6286,6291 ---- *************** *** 6263,6273 **** brush_lru = !brush_lru; } ! #if defined(FEAT_DIRECTX) ! if (IS_ENABLE_DIRECTX()) ! DWriteContext_FillRect(s_dwc, &rc, gui.currBgColor); ! #endif ! FillRect(s_hdc, &rc, hbr); SetBkMode(s_hdc, TRANSPARENT); --- 6348,6354 ---- brush_lru = !brush_lru; } ! fill_rect(&rc, hbr, gui.currBgColor); SetBkMode(s_hdc, TRANSPARENT); *************** *** 6462,6499 **** 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 */ 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. * Otherwise put the line just below the character. */ y = FILL_Y(row + 1) - 1; if (p_linespace > 1) y -= p_linespace - 1; ! MoveToEx(s_hdc, FILL_X(col), y, NULL); ! /* Note: LineTo() excludes the last pixel in the line. */ ! LineTo(s_hdc, FILL_X(col + len), y); ! DeleteObject(SelectObject(s_hdc, old_pen)); } /* Strikethrough */ 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; ! MoveToEx(s_hdc, FILL_X(col), y, NULL); ! /* Note: LineTo() excludes the last pixel in the line. */ ! LineTo(s_hdc, FILL_X(col + len), y); ! DeleteObject(SelectObject(s_hdc, old_pen)); } /* Undercurl */ --- 6543,6564 ---- foptions, pcliprect, (char *)text, len, padding); } /* Underline */ if (flags & DRAW_UNDERL) { /* When p_linespace is 0, overwrite the bottom row of pixels. * Otherwise put the line just below the character. */ y = FILL_Y(row + 1) - 1; if (p_linespace > 1) y -= p_linespace - 1; ! draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currFgColor); } /* Strikethrough */ if (flags & DRAW_STRIKE) { y = FILL_Y(row + 1) - gui.char_height/2; ! draw_line(FILL_X(col), y, FILL_X(col + len), y, gui.currSpColor); } /* Undercurl */ *************** *** 6507,6513 **** for (x = FILL_X(col); x < FILL_X(col + len); ++x) { offset = val[x % 8]; ! SetPixel(s_hdc, x, y - offset, gui.currSpColor); } } } --- 6572,6578 ---- for (x = FILL_X(col); x < FILL_X(col + len); ++x) { offset = val[x % 8]; ! set_pixel(x, y - offset, gui.currSpColor); } } } *************** *** 6541,6559 **** static void clear_rect(RECT *rcp) { ! HBRUSH hbr; ! ! #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); } --- 6606,6612 ---- static void clear_rect(RECT *rcp) { ! fill_rect(rcp, NULL, gui.back_pixel); } *** ../vim-8.0.1368/src/version.c 2017-12-05 13:06:12.279454348 +0100 --- src/version.c 2017-12-05 13:19:34.047220806 +0100 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1369, /**/ -- hundred-and-one symptoms of being an internet addict: 81. At social functions you introduce your husband as "my domain server." /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///