Class: Ray::PixelBus

Inherits:
Object
  • Object
show all
Defined in:
ext/pixel_bus.c,
lib/ray/pixel_bus.rb,
ext/pixel_bus.c

Overview

Pixel buses are a way to copy pixels from a target or an image onto an image without having to copy them to client memory, and possibly asynchronously. They may unfortunately not be available on some platforms.

Notice that pixels are stored from bottom to top in the buffer. You may have to rely on this when computing offsets manually.

Copying data collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type = :stream) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'ext/pixel_bus.c', line 37

static
VALUE ray_pixel_bus_init(int argc, VALUE *argv, VALUE self) {
  if (!say_pixel_bus_is_available())
    rb_raise(rb_eRuntimeError, "pixel buses aren't available on this platform");

  GLenum mode = SAY_STREAM;

  VALUE rb_mode = Qnil;
  rb_scan_args(argc, argv, "01", &rb_mode);

  if (!NIL_P(rb_mode)) mode = ray_buf_type(rb_mode);

  say_pixel_bus **ptr = NULL;
  Data_Get_Struct(self, say_pixel_bus*, ptr);

  *ptr = say_pixel_bus_create(mode);

  return self;
}

Class Method Details

.available?Boolean

Returns True if pixel buses are available on this platform.

Returns:

  • (Boolean)

    True if pixel buses are available on this platform



60
61
62
63
# File 'ext/pixel_bus.c', line 60

static
VALUE ray_pixel_bus_available(VALUE self) {
  return say_pixel_bus_is_available() ? Qtrue : Qfalse;
}

.unbindObject

Unbinds any pixel bus bound for either packing or unpacking



275
276
277
278
279
# File 'ext/pixel_bus.c', line 275

static
VALUE ray_pixel_bus_unbind(VALUE self) {
  say_pixel_bus_unbind();
  return Qnil;
}

.unbind_packObject

Unbinds any pixel bus bound for packing



284
285
286
287
288
# File 'ext/pixel_bus.c', line 284

static
VALUE ray_pixel_bus_unbind_pack(VALUE self) {
  say_pixel_bus_unbind_pack();
  return Qnil;
}

.unbind_unpackObject

Unbinds any pixel bus bound for unpacking



293
294
295
296
297
# File 'ext/pixel_bus.c', line 293

static
VALUE ray_pixel_bus_unbind_unpack(VALUE self) {
  say_pixel_bus_unbind_unpack();
  return Qnil;
}

Instance Method Details

#bindObject

Binds the pixel bus for packing and unpacking



248
249
250
251
252
# File 'ext/pixel_bus.c', line 248

static
VALUE ray_pixel_bus_bind(VALUE self) {
  say_pixel_bus_bind(ray_rb2pixel_bus(self));
  return self;
}

#bind_packObject

Binds the pixel bus for packing



257
258
259
260
261
# File 'ext/pixel_bus.c', line 257

static
VALUE ray_pixel_bus_bind_pack(VALUE self) {
  say_pixel_bus_bind_pack(ray_rb2pixel_bus(self));
  return self;
}

#bind_unpackObject

Binds the pixel bus for unpacking



266
267
268
269
270
# File 'ext/pixel_bus.c', line 266

static
VALUE ray_pixel_bus_bind_unpack(VALUE self) {
  say_pixel_bus_bind_unpack(ray_rb2pixel_bus(self));
  return self;
}

#copy(image, offset = 0) ⇒ Ray::Image

Duplicates an image through this bus

Parameters:

  • image (Ray::Image)

    Image to be copied

  • offset (Integer) (defaults to: 0)

    Offset to write the pixels to

Returns:



11
12
13
14
15
16
17
18
# File 'lib/ray/pixel_bus.rb', line 11

def copy(image, offset = 0)
  copy = Ray::Image.new image.size

  pull image, :offset => offset
  push copy,  :offset => offset

  copy
end

#pboInteger

Returns The identifier of the OpenGL buffer used by the PixelBus.

Returns:

  • (Integer)

    The identifier of the OpenGL buffer used by the PixelBus.



302
303
304
305
# File 'ext/pixel_bus.c', line 302

static
VALUE ray_pixel_bus_pbo(VALUE self) {
  return ULONG2NUM(say_pixel_bus_get_pbo(ray_rb2pixel_bus(self)));
}

#pull(object, opts = {}) ⇒ Integer

Pulls data from an object

This method reads a rectangle from an image on a target and stores it in the buffer, at a given offset. A rect can optionally be specified for targets. Otherwise, the whole object will be copied.

Parameters:

Options Hash (opts):

  • :offset (Integer) — default: 0

    Offset from the buffer

  • :rect (Ray::Rect, nil)

    Rect of pixels to read for targets

Returns:

  • (Integer)

    Offset of the last read element, plus one.

Raises:

  • (RangeError)

    If this method attempts to write outside of the buffer boundaries.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'ext/pixel_bus.c', line 123

static
VALUE ray_pixel_bus_pull(int argc, VALUE *argv, VALUE self) {
  say_pixel_bus *bus = ray_rb2pixel_bus(self);

  VALUE object, opts = Qnil;
  rb_scan_args(argc, argv, "11", &object, &opts);

  say_rect rect   = say_make_rect(0, 0, 0, 0);
  size_t   offset = 0;

  say_target *target = NULL;
  say_image  *image  = NULL;

  if (RAY_IS_A(object, rb_path2class("Ray::Target")))
    target = ray_rb2target(object);
  else
    image = ray_rb2image(object);

  say_vector2 size;

  if (target)
    size = say_target_get_size(target);
  else
    size = say_image_get_size(image);

  if (!NIL_P(opts)) {
    if (!RAY_IS_A(opts, rb_cHash)) {
      rb_raise(rb_eTypeError, "can't convert %s into Hash",
               RAY_OBJ_CLASSNAME(opts));
    }

    VALUE rb_rect   = rb_hash_aref(opts, RAY_SYM("rect"));
    VALUE rb_offset = rb_hash_aref(opts, RAY_SYM("offset"));

    if (target) {
      if (!NIL_P(rb_rect))
        rect = ray_convert_to_rect(rb_rect);
      else
        rect = say_make_rect(0, 0, size.x, size.y);
    }

    if (!NIL_P(rb_offset))
      offset = NUM2ULONG(rb_offset);
  }
  else if (target) {
    say_vector2 size = say_target_get_size(target);
    rect = say_make_rect(0, 0, size.x, size.y);
  }

  size_t ret = offset + (size_t)size.x * (size_t)size.y;
  if (ret > say_pixel_bus_get_size(bus))
    rb_raise(rb_eRangeError, "trying to write outside of buffer boundaries");

  if (target) {
    say_pixel_bus_pull_target(bus, target, offset,
                              rect.x, rect.y, rect.w, rect.h);
  }
  else {
    say_pixel_bus_pull_image(bus, image, offset);
  }

  return ULONG2NUM(ret);
}

#push(image, opts = {}) ⇒ Ray::PixelBus

Pushes data from the buffer onto an image

This method reads pixels from the buffer at a given offset, and copies them onto an image. A rect of pixels that must be replaced can be specifed. Otherwise, the whole texture will be replaced.

Parameters:

  • image (Ray::Image)

    Image to copy the rect to

Options Hash (opts):

  • :offset (Object) — default: see #pull
  • :rect (Ray::Rect)

    Rect of pixels to replace in the image

Returns:

Raises:

  • (RangeError)

    If this method tries to read pixels outside of the buffer boundaries or to write oustide of the image boundaries.



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'ext/pixel_bus.c', line 204

static
VALUE ray_pixel_bus_push(int argc, VALUE *argv, VALUE self) {
  say_pixel_bus *bus = ray_rb2pixel_bus(self);

  VALUE object, opts = Qnil;
  rb_scan_args(argc, argv, "11", &object, &opts);

  say_image *image = ray_rb2image(object);

  say_vector2 size = say_image_get_size(image);

  size_t offset = 0;
  say_rect rect = say_make_rect(0, 0, size.x, size.y);

  if (!NIL_P(opts)) {
    if (!RAY_IS_A(opts, rb_cHash)) {
      rb_raise(rb_eTypeError, "can't convert %s into Hash",
               RAY_OBJ_CLASSNAME(opts));
    }

    VALUE rb_rect   = rb_hash_aref(opts, RAY_SYM("rect"));
    VALUE rb_offset = rb_hash_aref(opts, RAY_SYM("offset"));

    if (!NIL_P(rb_rect))
      rect = ray_convert_to_rect(rb_rect);

    if (!NIL_P(rb_offset))
      offset = NUM2ULONG(rb_offset);
  }

  size_t ret = offset + ((size_t)rect.w * (size_t)rect.h);
  if (ret > say_pixel_bus_get_size(bus))
    rb_raise(rb_eRangeError, "trying to read outside of pixel bus boundaries");

  if (rect.x + rect.w > size.x || rect.y + rect.h > size.y)
    rb_raise(rb_eRangeError, "trying to write outsied of image boundaries");

  say_pixel_bus_push_image(bus, image, offset, rect.x, rect.y, rect.w, rect.h);
  return self;
}

#resize(new_size) ⇒ Object

Changes the capacity of the buffer

This method needs to copy the buffers content onto client memory, and is thus signinficantly slower than #resize!. It should not be called if the current content of the buffer doesn’t need to be read anymore.

Parameters:

  • new_size (Integer)

    New capacity of the buffer

See Also:



84
85
86
87
88
# File 'ext/pixel_bus.c', line 84

static
VALUE ray_pixel_bus_resize(VALUE self, VALUE size) {
  say_pixel_bus_resize(ray_rb2pixel_bus(self), NUM2ULONG(size));
  return self;
}

#resize!(new_size) ⇒ Object

Changes the capacity of the buffer without preserving content

This method allows to quickly resize the buffer used by the pixel bus. The content of the buffer is however undefined after this call.

See Also:



100
101
102
103
104
# File 'ext/pixel_bus.c', line 100

static
VALUE ray_pixel_bus_resize_fast(VALUE self, VALUE size) {
  say_pixel_bus_resize_fast(ray_rb2pixel_bus(self), NUM2ULONG(size));
  return self;
}

#sizeInteger

Returns The capacity of the pixel bus, in pixels.

Returns:

  • (Integer)

    The capacity of the pixel bus, in pixels



68
69
70
71
# File 'ext/pixel_bus.c', line 68

static
VALUE ray_pixel_bus_size(VALUE self) {
  return ULONG2NUM(say_pixel_bus_get_size(ray_rb2pixel_bus(self)));
}