diff options
author | Po Lu <luangruo@yahoo.com> | 2022-04-29 11:33:41 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-04-30 11:20:46 +0800 |
commit | bc44455f778a256a861c8063e87a662a13f603e1 (patch) | |
tree | a7426525ab8b5a9d9ca5fc28633e45d0dd3bb5c1 /src/w32xfns.c | |
parent | a33bf0114920a67926761ec2f51c040265b8dfd1 (diff) | |
download | emacs-bc44455f778a256a861c8063e87a662a13f603e1.tar.gz emacs-bc44455f778a256a861c8063e87a662a13f603e1.tar.bz2 emacs-bc44455f778a256a861c8063e87a662a13f603e1.zip |
Implement double buffering on MS Windows
* etc/NEWS: Announce changes.
* src/w32fns.c (w32_set_inhibit_double_buffering): New function.
(w32_wnd_proc):
(Fx_create_frame):
(w32_create_tip_frame): Set `inhibit-double-buffering' parameter.
(w32_frame_parm_handlers): Add new handler.
* src/w32term.c (w32_show_back_buffer):
(w32_release_paint_buffer): New functions.
(w32_frame_up_to_date): Show back buffer if applicable.
(w32_buffer_flipping_unblocked_hook): New hook.
(w32_scroll_run): Use BitBlt to scroll instead of window
scrolling functions.
(w32_scroll_bar_clear): Don't clear scroll bars when double
buffered.
(w32_read_socket): Flip buffers after reading input events in
some cases.
(w32_free_frame_resources): Free back buffer.
(w32_create_terminal): Add new hook.
* src/w32term.h (struct w32_output): New fields for handling
back buffers.
* src/w32xfns.c (select_palette): Fix indentation.
(get_frame_dc, release_frame_dc): Return back buffer when
appropriate and set dirty flag.
Diffstat (limited to 'src/w32xfns.c')
-rw-r--r-- | src/w32xfns.c | 76 |
1 files changed, 66 insertions, 10 deletions
diff --git a/src/w32xfns.c b/src/w32xfns.c index d5974b906e8..139985c5bdb 100644 --- a/src/w32xfns.c +++ b/src/w32xfns.c @@ -136,13 +136,13 @@ select_palette (struct frame *f, HDC hdc) f->output_data.w32->old_palette = NULL; if (RealizePalette (hdc) != GDI_ERROR) - { - Lisp_Object frame, framelist; - FOR_EACH_FRAME (framelist, frame) { - SET_FRAME_GARBAGED (XFRAME (frame)); + Lisp_Object frame, framelist; + FOR_EACH_FRAME (framelist, frame) + { + SET_FRAME_GARBAGED (XFRAME (frame)); + } } - } } void @@ -157,19 +157,68 @@ deselect_palette (struct frame *f, HDC hdc) HDC get_frame_dc (struct frame *f) { - HDC hdc; + HDC hdc, paint_dc; + HBITMAP back_buffer; + HGDIOBJ obj; + struct w32_output *output; if (f->output_method != output_w32) emacs_abort (); enter_crit (); + output = FRAME_OUTPUT_DATA (f); + + if (output->paint_dc) + { + if (output->paint_buffer_width != FRAME_PIXEL_WIDTH (f) + || output->paint_buffer_height != FRAME_PIXEL_HEIGHT (f)) + w32_release_paint_buffer (f); + else + { + output->paint_buffer_dirty = 1; + return output->paint_dc; + } + } - hdc = GetDC (f->output_data.w32->window_desc); + hdc = GetDC (output->window_desc); /* If this gets called during startup before the frame is valid, there is a chance of corrupting random data or crashing. */ if (hdc) - select_palette (f, hdc); + { + select_palette (f, hdc); + + if (FRAME_OUTPUT_DATA (f)->want_paint_buffer) + { + back_buffer + = CreateCompatibleBitmap (hdc, FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f)); + + if (back_buffer) + { + paint_dc = CreateCompatibleDC (hdc); + + if (!paint_dc) + DeleteObject (back_buffer); + else + { + obj = SelectObject (paint_dc, back_buffer); + + output->paint_dc_object = obj; + output->paint_dc = paint_dc; + output->paint_buffer_handle = hdc; + output->paint_buffer = back_buffer; + output->paint_buffer_width = FRAME_PIXEL_WIDTH (f); + output->paint_buffer_height = FRAME_PIXEL_HEIGHT (f); + output->paint_buffer_dirty = 1; + + SET_FRAME_GARBAGED (f); + + return paint_dc; + } + } + } + } return hdc; } @@ -179,8 +228,15 @@ release_frame_dc (struct frame *f, HDC hdc) { int ret; - deselect_palette (f, hdc); - ret = ReleaseDC (f->output_data.w32->window_desc, hdc); + /* Avoid releasing the double-buffered DC here, since it'll be + released upon the next buffer flip instead. */ + if (hdc != FRAME_OUTPUT_DATA (f)->paint_dc) + { + deselect_palette (f, hdc); + ret = ReleaseDC (f->output_data.w32->window_desc, hdc); + } + else + ret = 0; leave_crit (); |