| 1 | /* SPDX-License-Identifier: MIT */ |
|---|---|
| 2 | /* |
| 3 | * Copyright © 2023 Intel Corporation |
| 4 | */ |
| 5 | |
| 6 | #ifndef __I915_GEM_OBJECT_FRONTBUFFER_H__ |
| 7 | #define __I915_GEM_OBJECT_FRONTBUFFER_H__ |
| 8 | |
| 9 | #include <linux/kref.h> |
| 10 | #include <linux/rcupdate.h> |
| 11 | |
| 12 | #include "display/intel_frontbuffer.h" |
| 13 | #include "i915_gem_object_types.h" |
| 14 | |
| 15 | struct i915_frontbuffer { |
| 16 | struct intel_frontbuffer base; |
| 17 | struct drm_i915_gem_object *obj; |
| 18 | struct i915_active write; |
| 19 | struct rcu_head rcu; |
| 20 | struct kref ref; |
| 21 | }; |
| 22 | |
| 23 | void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, |
| 24 | enum fb_op_origin origin); |
| 25 | void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, |
| 26 | enum fb_op_origin origin); |
| 27 | |
| 28 | static inline void |
| 29 | i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, |
| 30 | enum fb_op_origin origin) |
| 31 | { |
| 32 | if (unlikely(rcu_access_pointer(obj->frontbuffer))) |
| 33 | __i915_gem_object_flush_frontbuffer(obj, origin); |
| 34 | } |
| 35 | |
| 36 | static inline void |
| 37 | i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, |
| 38 | enum fb_op_origin origin) |
| 39 | { |
| 40 | if (unlikely(rcu_access_pointer(obj->frontbuffer))) |
| 41 | __i915_gem_object_invalidate_frontbuffer(obj, origin); |
| 42 | } |
| 43 | |
| 44 | struct i915_frontbuffer *i915_gem_object_frontbuffer_get(struct drm_i915_gem_object *obj); |
| 45 | void i915_gem_object_frontbuffer_ref(struct i915_frontbuffer *front); |
| 46 | void i915_gem_object_frontbuffer_put(struct i915_frontbuffer *front); |
| 47 | |
| 48 | /** |
| 49 | * i915_gem_object_frontbuffer_lookup - Look up the object's frontbuffer |
| 50 | * @obj: The object whose frontbuffer to look up. |
| 51 | * |
| 52 | * Get pointer to object's frontbuffer if such exists. Please note that RCU |
| 53 | * mechanism is used to handle e.g. ongoing removal of frontbuffer pointer. |
| 54 | * |
| 55 | * Return: pointer to object's frontbuffer is such exists or NULL |
| 56 | */ |
| 57 | static inline struct i915_frontbuffer * |
| 58 | i915_gem_object_frontbuffer_lookup(const struct drm_i915_gem_object *obj) |
| 59 | { |
| 60 | struct i915_frontbuffer *front; |
| 61 | |
| 62 | if (likely(!rcu_access_pointer(obj->frontbuffer))) |
| 63 | return NULL; |
| 64 | |
| 65 | rcu_read_lock(); |
| 66 | do { |
| 67 | front = rcu_dereference(obj->frontbuffer); |
| 68 | if (!front) |
| 69 | break; |
| 70 | |
| 71 | if (unlikely(!kref_get_unless_zero(&front->ref))) |
| 72 | continue; |
| 73 | |
| 74 | if (likely(front == rcu_access_pointer(obj->frontbuffer))) |
| 75 | break; |
| 76 | |
| 77 | i915_gem_object_frontbuffer_put(front); |
| 78 | } while (1); |
| 79 | rcu_read_unlock(); |
| 80 | |
| 81 | return front; |
| 82 | } |
| 83 | |
| 84 | #endif |
| 85 |
