diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2017-02-17 10:58:08 +0100 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2017-02-17 10:58:08 +0100 |
commit | 35730491ef90528be367b5c59261ec82984b50e0 (patch) | |
tree | 8318453dd40404ddcb02ff86e10403f8698c2a75 /plugingui/window.cc | |
parent | 27942ce1947d3fcd18b67702f4565bb399441bb8 (diff) |
Add partial rendering support when rendering widgets to window pixel buffer and also when rendering window pixel buffer to native window. Win32 only partially implemented.
Diffstat (limited to 'plugingui/window.cc')
-rw-r--r-- | plugingui/window.cc | 79 |
1 files changed, 65 insertions, 14 deletions
diff --git a/plugingui/window.cc b/plugingui/window.cc index 44c8e12..e2a5b58 100644 --- a/plugingui/window.cc +++ b/plugingui/window.cc @@ -26,6 +26,8 @@ */ #include "window.h" +#include <cstring> + #include "painter.h" #ifndef PUGL @@ -224,39 +226,88 @@ bool Window::updateBuffer() return false; } - for(const auto& pixelBuffer : getPixelBuffers()) + bool has_dirty_rect{false}; + Rect dirty_rect; + + auto pixel_buffers = getPixelBuffers(); + for(auto& pixel_buffer : pixel_buffers) { - size_t updateWidth = pixelBuffer->width; - size_t updateHeight = pixelBuffer->height; + if(pixel_buffer->dirty) + { + auto x1 = (std::size_t)pixel_buffer->x; + auto x2 = (std::size_t)(pixel_buffer->x + pixel_buffer->width); + auto y1 = (std::size_t)pixel_buffer->y; + auto y2 = (std::size_t)(pixel_buffer->y + pixel_buffer->height); + + pixel_buffer->dirty = false; + if(!has_dirty_rect) + { + // Insert this area: + dirty_rect = {x1, y1, x2, y2}; + has_dirty_rect = true; + } + else + { + // Expand existing area: + auto x1_0 = dirty_rect.x1; + auto y1_0 = dirty_rect.y1; + auto x2_0 = dirty_rect.x2; + auto y2_0 = dirty_rect.y2; + dirty_rect = { + (x1_0 < x1) ? x1_0 : x1, + (y1_0 < y1) ? y1_0 : y1, + (x2_0 > x2) ? x2_0 : x2, + (y2_0 > y2) ? y2_0 : y2 + }; + } + } + } + + for(auto& pixel_buffer : pixel_buffers) + { + int update_width = pixel_buffer->width; + int update_height = pixel_buffer->height; // Skip buffer if not inside window. - if((wpixbuf.width < pixelBuffer->x) || (wpixbuf.height < pixelBuffer->y)) + if(((int)wpixbuf.width < pixel_buffer->x) || + ((int)wpixbuf.height < pixel_buffer->y)) { continue; } - if(updateWidth > (wpixbuf.width - pixelBuffer->x)) + if(update_width > ((int)wpixbuf.width - pixel_buffer->x)) { - updateWidth = (wpixbuf.width - pixelBuffer->x); + update_width = ((int)wpixbuf.width - pixel_buffer->x); } - if(updateHeight > (wpixbuf.height - pixelBuffer->y)) + if(update_height > ((int)wpixbuf.height - pixel_buffer->y)) { - updateHeight = (wpixbuf.height - pixelBuffer->y); + update_height = ((int)wpixbuf.height - pixel_buffer->y); } - unsigned char r,g,b,a; - for(size_t y = 0; y < updateHeight; y++) + std::uint8_t r, g, b, a; + + auto from_x = (int)dirty_rect.x1 - pixel_buffer->x; + from_x = std::max(0, from_x); + auto from_y = (int)dirty_rect.y1 - pixel_buffer->y; + from_y = std::max(0, from_y); + + auto to_x = (int)dirty_rect.x2 - pixel_buffer->x; + to_x = std::min(to_x, (int)update_width); + auto to_y = (int)dirty_rect.y2 - pixel_buffer->y; + to_y = std::min(to_y, (int)update_height); + + for(int y = from_y; y < to_y; y++) { - for(size_t x = 0; x < updateWidth; x++) + for(int x = from_x; x < to_x; x++) { - pixelBuffer->pixel(x, y, &r, &g, &b, &a); - wpixbuf.setPixel(x + pixelBuffer->x, y + pixelBuffer->y, r, g, b, a); + pixel_buffer->pixel(x, y, &r, &g, &b, &a); + wpixbuf.setPixel(x + pixel_buffer->x, y + pixel_buffer->y, r, g, b, a); } } } - native->redraw(); + native->redraw(dirty_rect); needs_redraw = false; return true; |