downscale.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import GObject from 'gi://GObject';
  2. import * as utils from '../conveniences/utils.js';
  3. const Shell = await utils.import_in_shell_only('gi://Shell');
  4. const Clutter = await utils.import_in_shell_only('gi://Clutter');
  5. const SHADER_FILENAME = 'downscale.glsl';
  6. const DEFAULT_PARAMS = {
  7. divider: 8, downsampling_mode: 0, width: 0, height: 0
  8. };
  9. export const DownscaleEffect = utils.IS_IN_PREFERENCES ?
  10. { default_params: DEFAULT_PARAMS } :
  11. new GObject.registerClass({
  12. GTypeName: "DownscaleEffect",
  13. Properties: {
  14. 'divider': GObject.ParamSpec.int(
  15. `divider`,
  16. `Divider`,
  17. `Divider`,
  18. GObject.ParamFlags.READWRITE,
  19. 0, 64,
  20. 8,
  21. ),
  22. 'downsampling_mode': GObject.ParamSpec.int(
  23. `downsampling_mode`,
  24. `Downsampling mode`,
  25. `Downsampling mode`,
  26. GObject.ParamFlags.READWRITE,
  27. 0, 2,
  28. 0,
  29. ),
  30. 'width': GObject.ParamSpec.double(
  31. `width`,
  32. `Width`,
  33. `Width`,
  34. GObject.ParamFlags.READWRITE,
  35. 0.0, Number.MAX_SAFE_INTEGER,
  36. 0.0,
  37. ),
  38. 'height': GObject.ParamSpec.double(
  39. `height`,
  40. `Height`,
  41. `Height`,
  42. GObject.ParamFlags.READWRITE,
  43. 0.0, Number.MAX_SAFE_INTEGER,
  44. 0.0,
  45. )
  46. }
  47. }, class DownscaleEffect extends Clutter.ShaderEffect {
  48. constructor(params) {
  49. super(params);
  50. utils.setup_params(this, params);
  51. // set shader source
  52. this._source = utils.get_shader_source(Shell, SHADER_FILENAME, import.meta.url);
  53. if (this._source)
  54. this.set_shader_source(this._source);
  55. }
  56. static get default_params() {
  57. return DEFAULT_PARAMS;
  58. }
  59. get divider() {
  60. return this._divider;
  61. }
  62. set divider(value) {
  63. if (this._divider !== value) {
  64. this._divider = value;
  65. this.set_uniform_value('divider', this._divider);
  66. }
  67. }
  68. get downsampling_mode() {
  69. return this._downsampling_mode;
  70. }
  71. set downsampling_mode(value) {
  72. if (this._downsampling_mode !== value) {
  73. this._downsampling_mode = value;
  74. this.set_uniform_value('downsampling_mode', this._downsampling_mode);
  75. }
  76. }
  77. get width() {
  78. return this._width;
  79. }
  80. set width(value) {
  81. if (this._width !== value) {
  82. this._width = value;
  83. this.set_uniform_value('width', parseFloat(this._width - 1e-6));
  84. }
  85. }
  86. get height() {
  87. return this._height;
  88. }
  89. set height(value) {
  90. if (this._height !== value) {
  91. this._height = value;
  92. this.set_uniform_value('height', parseFloat(this._height - 1e-6));
  93. }
  94. }
  95. vfunc_set_actor(actor) {
  96. if (this._actor_connection_size_id) {
  97. let old_actor = this.get_actor();
  98. old_actor?.disconnect(this._actor_connection_size_id);
  99. }
  100. if (actor) {
  101. this.width = actor.width;
  102. this.height = actor.height;
  103. this._actor_connection_size_id = actor.connect('notify::size', _ => {
  104. this.width = actor.width;
  105. this.height = actor.height;
  106. });
  107. }
  108. else
  109. this._actor_connection_size_id = null;
  110. super.vfunc_set_actor(actor);
  111. }
  112. vfunc_paint_target(paint_node, paint_context) {
  113. // force setting nearest-neighbour texture filtering
  114. this.get_pipeline().set_layer_filters(0, 9728, 9728);
  115. super.vfunc_paint_target(paint_node, paint_context);
  116. }
  117. });