[Bf-blender-cvs] [498f079d2c3] master: GHOST/Wayland: support displaying custom software cursors

Campbell Barton noreply at git.blender.org
Sat Jun 18 09:21:10 CEST 2022


Commit: 498f079d2c3644b47ff5c004bc1cf93a9ba6604b
Author: Campbell Barton
Date:   Sat Jun 18 15:10:03 2022 +1000
Branches: master
https://developer.blender.org/rB498f079d2c3644b47ff5c004bc1cf93a9ba6604b

GHOST/Wayland: support displaying custom software cursors

Add a method to access the custom cursor from GHOST which is used
for drawing a software cursor. This means the knife tools cursor now
work as expected.

Although non-custom cursors are still not supported.

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IWindow.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_Window.cpp
M	intern/ghost/intern/GHOST_Window.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp
M	intern/ghost/intern/GHOST_WindowWayland.h
M	source/blender/windowmanager/intern/wm_draw.c

===================================================================

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 08ca9603985..5ace0fcc9d2 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -364,6 +364,9 @@ extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle
                                                  int hotY,
                                                  bool canInvertColor);
 
+extern GHOST_TSuccess GHOST_GetCursorBitmap(GHOST_WindowHandle windowhandle,
+                                            GHOST_CursorBitmapRef *bitmap);
+
 /**
  * Returns the visibility state of the cursor.
  * \param windowhandle: The handle to the window.
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index f9552246e89..f712d9bd9f0 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -285,6 +285,8 @@ class GHOST_IWindow {
                                               int hotY,
                                               bool canInvertColor) = 0;
 
+  virtual GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) = 0;
+
   /**
    * Returns the visibility state of the cursor.
    * \return The visibility state of the cursor.
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 78f2b24ea78..35bde3d4413 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -44,6 +44,16 @@ GHOST_DECLARE_HANDLE(GHOST_XrContextHandle);
 
 typedef void (*GHOST_TBacktraceFn)(void *file_handle);
 
+/**
+ * A reference to cursor bitmap data.
+ */
+typedef struct {
+  /** `RGBA` bytes. */
+  const uint8_t *data;
+  int data_size[2];
+  int hot_spot[2];
+} GHOST_CursorBitmapRef;
+
 typedef struct {
   int flags;
 } GHOST_GLSettings;
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 032ecd6aab5..2b5414cd47b 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -326,6 +326,14 @@ GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
   return window->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
 }
 
+GHOST_TSuccess GHOST_GetCursorBitmap(GHOST_WindowHandle windowhandle,
+                                     GHOST_CursorBitmapRef *bitmap)
+{
+  GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+  return window->getCursorBitmap(bitmap);
+}
+
 bool GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle)
 {
   GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index bff96b3c0a4..aebee003145 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -96,6 +96,7 @@ struct buffer_t {
 
 struct cursor_t {
   bool visible = false;
+  bool is_custom = false;
   struct wl_surface *wl_surface = nullptr;
   struct wl_buffer *wl_buffer = nullptr;
   struct wl_cursor_image wl_image = {0};
@@ -2587,6 +2588,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
     return GHOST_kFailure;
   }
 
+  c->is_custom = false;
   c->wl_buffer = buffer;
   c->wl_image = *image;
 
@@ -2650,6 +2652,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
       nullptr, cursor->file_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
   if (cursor->file_buffer->data == MAP_FAILED) {
+    cursor->file_buffer->data = nullptr;
     close(fd);
     return GHOST_kFailure;
   }
@@ -2694,6 +2697,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
     }
   }
 
+  cursor->is_custom = true;
   cursor->wl_buffer = buffer;
   cursor->wl_image.width = uint32_t(sizex);
   cursor->wl_image.height = uint32_t(sizey);
@@ -2705,6 +2709,27 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
   return GHOST_kSuccess;
 }
 
+GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
+{
+  cursor_t *cursor = &d->inputs[0]->cursor;
+  if (cursor->file_buffer->data == nullptr) {
+    return GHOST_kFailure;
+  }
+  if (!cursor->is_custom) {
+    return GHOST_kFailure;
+  }
+
+  bitmap->data_size[0] = cursor->wl_image.width;
+  bitmap->data_size[1] = cursor->wl_image.height;
+
+  bitmap->hot_spot[0] = cursor->wl_image.hotspot_x;
+  bitmap->hot_spot[1] = cursor->wl_image.hotspot_y;
+
+  bitmap->data = (uint8_t *)static_cast<void *>(cursor->file_buffer->data);
+
+  return GHOST_kSuccess;
+}
+
 GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible)
 {
   if (d->inputs.empty()) {
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 6faff8d57c1..04aa4063947 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -122,6 +122,8 @@ class GHOST_SystemWayland : public GHOST_System {
                                       int hotY,
                                       bool canInvertColor);
 
+  GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap);
+
   GHOST_TSuccess setCursorVisibility(bool visible);
 
   bool supportsCursorWarp();
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index d6dcb269c8f..3f093840d0c 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -208,6 +208,12 @@ GHOST_TSuccess GHOST_Window::setCustomCursorShape(
   return GHOST_kFailure;
 }
 
+GHOST_TSuccess GHOST_Window::getCursorBitmap(GHOST_CursorBitmapRef * /*bitmap*/)
+{
+  /* Sub-classes may override. */
+  return GHOST_kFailure;
+}
+
 void GHOST_Window::setAcceptDragOperation(bool canAccept)
 {
   m_canAcceptDragOperation = canAccept;
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 6ca2651fad0..5ff91c05b16 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -117,6 +117,8 @@ class GHOST_Window : public GHOST_IWindow {
                                       int hotY,
                                       bool canInvertColor);
 
+  GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap);
+
   /**
    * Returns the visibility state of the cursor.
    * \return The visibility state of the cursor.
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 8c7183971ab..941e08ff035 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -503,6 +503,11 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(
   return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
 }
 
+GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
+{
+  return m_system->getCursorBitmap(bitmap);
+}
+
 void GHOST_WindowWayland::setTitle(const char *title)
 {
   xdg_toplevel_set_title(w->xdg_toplevel, title);
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index f9effc636a1..d1eadd8fcd4 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -54,6 +54,8 @@ class GHOST_WindowWayland : public GHOST_Window {
                                             bool canInvertColor) override;
   bool getCursorGrabUseSoftwareDisplay() override;
 
+  GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) override;
+
   void setTitle(const char *title) override;
 
   std::string getTitle() const override;
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index abf7aa65da7..aaa28b1fd85 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -41,6 +41,7 @@
 #include "GPU_debug.h"
 #include "GPU_framebuffer.h"
 #include "GPU_immediate.h"
+#include "GPU_matrix.h"
 #include "GPU_state.h"
 #include "GPU_texture.h"
 #include "GPU_viewport.h"
@@ -193,27 +194,69 @@ static void wm_software_cursor_motion_clear(void)
   g_software_cursor.xy[1] = -1;
 }
 
-static void wm_software_cursor_draw(wmWindow *win, const struct GrabState *grab_state)
+static void wm_software_cursor_draw_bitmap(const int event_xy[2],
+                                           const GHOST_CursorBitmapRef *bitmap)
 {
-  int x = win->eventstate->xy[0];
-  int y = win->eventstate->xy[1];
+  GPU_blend(GPU_BLEND_ALPHA);
 
-  if (grab_state->wrap_axis & GHOST_kAxisX) {
-    const int min = grab_state->bounds[0];
-    const int max = grab_state->bounds[2];
-    if (min != max) {
-      x = mod_i(x - min, max - min) + min;
-    }
-  }
-  if (grab_state->wrap_axis & GHOST_kGrabAxisY) {
-    const int height = WM_window_pixels_y(win);
-    const int min = height - grab_state->bounds[1];
-    const int max = height - grab_state->bounds[3];
-    if (min != max) {
-      y = mod_i(y - max, min - max) + max;
-    }
-  }
+  float gl_matrix[4][4];
+  GPUTexture *texture = GPU_texture_create_2d(
+      "softeare_cursor", bitmap->data_size[0], bitmap->data_size[1], 1, GPU_RGBA8, NULL);
+  GPU_texture_update(texture, GPU_DATA_UBYTE, bitmap->data);
+  GPU_texture_filter_mode(texture, false);
+
+  GPU_matrix_push();
+
+  const int scale = (int)U.pixelsize;
+
+  unit_m4(gl_matrix);
+
+  gl_matrix[3][0] = event_xy[0] - (bitmap->hot_spot[0] * scale);
+  gl_matrix[3][1] = event_xy[1] - ((bitmap->data_size[1] - bitmap->hot_spot[1]) * scale);
+
+  gl_matrix[0][0] = bitmap->data_size[0] * scale;
+  gl_matrix[1][1] = bitmap->data_size[1] * scale;
+
+  GPU_matrix_mul(gl_matrix);
+
+  GPUVertFormat *imm_format = immVertexFormat();
+  uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+  uint texCoord = GPU_vertformat_attr_add(
+      imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+  /* Use 3D image for correct display of planar tracked images. */
+  immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+
+  immBindTexture("image", texture);
+  immUniform1f("alpha", 1.0f);
+
+  immBegin(GPU_PRIM_TRI_FAN, 4);
+
+  immAttr2f(texCoord, 0.0f, 1.0f);
+  immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+
+  immAt

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list