浏览代码

win-capture: Cache cursor textures to prevent reallocation

Whenever a cursor is captured and the cursor icon changes, it creates a
new texture.  This isn't particularly optimal, so instead just store a
cache of cursor textures (based on size), and make the textures dynamic.
Doing this will prevent unnecessary texture reallocation.
jp9000 9 年之前
父节点
当前提交
81ab13a2a4
共有 2 个文件被更改,包括 41 次插入6 次删除
  1. 30 6
      plugins/win-capture/cursor-capture.c
  2. 11 0
      plugins/win-capture/cursor-capture.h

+ 30 - 6
plugins/win-capture/cursor-capture.c

@@ -131,6 +131,25 @@ static inline uint8_t *cursor_capture_icon_bitmap(ICONINFO *ii,
 	return output;
 }
 
+static gs_texture_t *get_cached_texture(struct cursor_data *data,
+		uint32_t cx, uint32_t cy)
+{
+	struct cached_cursor cc;
+
+	for (size_t i = 0; i < data->cached_textures.num; i++) {
+		struct cached_cursor *pcc = &data->cached_textures.array[i];
+
+		if (pcc->cx == cx && pcc->cy == cy)
+			return pcc->texture;
+	}
+
+	cc.texture = gs_texture_create(cx, cy, GS_BGRA, 1, NULL, GS_DYNAMIC);
+	cc.cx = cx;
+	cc.cy = cy;
+	da_push_back(data->cached_textures, &cc);
+	return cc.texture;
+}
+
 static inline bool cursor_capture_icon(struct cursor_data *data, HICON icon)
 {
 	uint8_t *bitmap;
@@ -138,9 +157,6 @@ static inline bool cursor_capture_icon(struct cursor_data *data, HICON icon)
 	uint32_t width;
 	ICONINFO ii;
 
-	gs_texture_destroy(data->texture);
-	data->texture = NULL;
-
 	if (!icon) {
 		return false;
 	}
@@ -150,8 +166,12 @@ static inline bool cursor_capture_icon(struct cursor_data *data, HICON icon)
 
 	bitmap = cursor_capture_icon_bitmap(&ii, &width, &height);
 	if (bitmap) {
-		data->texture = gs_texture_create(width, height, GS_BGRA,
-				1, (const uint8_t**)&bitmap, 0);
+		if (data->last_cx != width && data->last_cy != height) {
+			data->texture = get_cached_texture(data, width, height);
+			data->last_cx = width;
+			data->last_cy = height;
+		}
+		gs_texture_set_image(data->texture, bitmap, width * 4, false);
 		bfree(bitmap);
 
 		data->x_hotspot = ii.xHotspot;
@@ -217,6 +237,10 @@ void cursor_draw(struct cursor_data *data, long x_offset, long y_offset,
 
 void cursor_data_free(struct cursor_data *data)
 {
-	gs_texture_destroy(data->texture);
+	for (size_t i = 0; i < data->cached_textures.num; i++) {
+		struct cached_cursor *pcc = &data->cached_textures.array[i];
+		gs_texture_destroy(pcc->texture);
+	}
+	da_free(data->cached_textures);
 	memset(data, 0, sizeof(*data));
 }

+ 11 - 0
plugins/win-capture/cursor-capture.h

@@ -2,6 +2,12 @@
 
 #include <stdint.h>
 
+struct cached_cursor {
+	gs_texture_t *texture;
+	uint32_t cx;
+	uint32_t cy;
+};
+
 struct cursor_data {
 	gs_texture_t                   *texture;
 	HCURSOR                        current_cursor;
@@ -9,6 +15,11 @@ struct cursor_data {
 	long                           x_hotspot;
 	long                           y_hotspot;
 	bool                           visible;
+
+	uint32_t                       last_cx;
+	uint32_t                       last_cy;
+
+	DARRAY(struct cached_cursor)   cached_textures;
 };
 
 extern void cursor_capture(struct cursor_data *data);