Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions docs/sphere2-core-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,34 @@ new Surface(width, height[, content]); [API 1]
enough pixel data to cover the entire surface, a RangeError will be
thrown.

new Surface(width, height[, options]); [NEW]

Constructs a new Surface with the specified options. `width` and `height`
specify the size in pixels of the surface.

The following are all optional:

options.color
A `Color` with which the surface will be filled. The default is
`Color.Transparent`.

options.content:
A buffer object holding the RGBA pixel data to use to initialize the
image. The pixel data should not be padded (i.e. stride equal to
width).

options.multisample
The number of samples to use for multisample antialiasing. The default
value is 0, which means multisampling is not enabled. A value of 1
would mean one sample per pixel, effectively the same as not being
enabled. Normal values would be multiples of 2.

This effectively multiplies the resolution of the texture by the value
you choose internally, so can have a large effect on performance and
texture size.

If `content` is specified, both `color` and `multisample` will be ignored.

new Surface(filename); [API 1]

Loads the image file named by `filename` synchronously, without yielding to
Expand Down Expand Up @@ -2276,6 +2304,34 @@ new Texture(width, height[, content]); [API 1]
enough pixel data to cover the entire texture, a RangeError will be
thrown.

new Texture(width, height[, options]); [NEW]

Constructs a new Texture with the specified options. `width` and `height`
specify the size in pixels of the surface.

The following are all optional:

options.color
A `Color` with which the texture will be filled. The default is
`Color.Transparent`.

options.content:
A buffer object holding the RGBA pixel data to use to initialize the
image. The pixel data should not be padded (i.e. stride equal to
width).

options.multisample
The number of samples to use for multisample antialiasing. The default
value is 0, which means multisampling is not enabled. A value of 1
would mean one sample per pixel, effectively the same as not being
enabled. Normal values would be multiples of 2.

This effectively multiplies the resolution of the texture by the value
you choose internally, so can have a large effect on performance and
texture size.

If `content` is specified, both `color` and `multisample` will be ignored.

new Texture(surface); [API 1]

Constructs a new Texture from the contents of `surface`, a Surface object.
Expand Down
2 changes: 1 addition & 1 deletion src/minisphere/animation.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ mng_cb_processheader(mng_handle stream, mng_uint32 width, mng_uint32 height)
anim->w = width;
anim->h = height;
image_unref(anim->frame);
if (!(anim->frame = image_new(anim->w, anim->h, NULL)))
if (!(anim->frame = image_new(anim->w, anim->h, NULL, 0)))
goto on_error;
mng_set_canvasstyle(stream, MNG_CANVAS_RGBA8);
return MNG_TRUE;
Expand Down
2 changes: 1 addition & 1 deletion src/minisphere/atlas.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ atlas_new(int num_images, int max_width, int max_height)
atlas->max_width = max_width;
atlas->max_height = max_height;
atlas->size = mk_rect(0, 0, atlas->pitch * atlas->max_width, atlas->pitch * atlas->max_height);
if (!(atlas->image = image_new(atlas->size.x2, atlas->size.y2, NULL)))
if (!(atlas->image = image_new(atlas->size.x2, atlas->size.y2, NULL, 0)))
goto on_error;

atlas->id = s_next_atlas_id++;
Expand Down
2 changes: 1 addition & 1 deletion src/minisphere/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ font_load(const char* filename)
n_glyphs_per_row = ceil(sqrt(rfn.num_chars));
atlas_size_x = max_x * n_glyphs_per_row;
atlas_size_y = max_y * n_glyphs_per_row;
if ((atlas = image_new(atlas_size_x, atlas_size_y, NULL)) == NULL)
if ((atlas = image_new(atlas_size_x, atlas_size_y, NULL, 0)) == NULL)
goto on_error;

// pass 2: load glyph data
Expand Down
29 changes: 28 additions & 1 deletion src/minisphere/galileo.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,27 @@ shader_ref(shader_t* it)
void
shader_unref(shader_t* it)
{
struct uniform* uniform;

iter_t iter;

if (it == NULL || --it->refcount > 0)
return;

console_log(3, "disposing shader program #%u no longer in use", it->id);

iter = vector_enum(it->uniforms);
while ((uniform = iter_next(&iter))) {
switch (uniform->type) {
case UNIFORM_FLOAT_ARR:
free(uniform->float_list);
break;
case UNIFORM_INT_ARR:
free(uniform->int_list);
break;
}
}

al_destroy_shader(it->program);
vector_free(it->uniforms);
free(it);
Expand Down Expand Up @@ -831,8 +848,18 @@ free_cached_uniform(shader_t* shader, const char* name)

iter = vector_enum(shader->uniforms);
while ((uniform = iter_next(&iter))) {
if (strcmp(uniform->name, name) == 0)
if (strcmp(uniform->name, name) == 0) {
switch (uniform->type) {
case UNIFORM_FLOAT_ARR:
free(uniform->float_list);
break;
case UNIFORM_INT_ARR:
free(uniform->int_list);
break;
}

iter_remove(&iter);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/minisphere/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static image_t* s_last_image = NULL;
static unsigned int s_next_image_id = 0;

image_t*
image_new(int width, int height, const color_t* pixels)
image_new(int width, int height, const color_t* pixels, int multisample)
{
image_t* image;
ALLEGRO_BITMAP* old_target;
Expand All @@ -76,6 +76,7 @@ image_new(int width, int height, const color_t* pixels)
if (!(image = calloc(1, sizeof(image_t))))
goto on_error;
al_set_new_bitmap_depth(16);
al_set_new_bitmap_samples(multisample);
if ((image->bitmap = al_create_bitmap(width, height)) == NULL)
goto on_error;
image->id = s_next_image_id++;
Expand Down
2 changes: 1 addition & 1 deletion src/minisphere/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct image_lock
ptrdiff_t pitch;
} image_lock_t;

image_t* image_new (int width, int height, const color_t* pixels);
image_t* image_new (int width, int height, const color_t* pixels, int multisample);
image_t* image_new_slice (image_t* parent, int x, int y, int width, int height);
image_t* image_dup (const image_t* it);
image_t* image_load (const char* filename);
Expand Down
37 changes: 35 additions & 2 deletions src/minisphere/pegasus.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,11 @@ static mixer_t* s_def_mixer;
static js_ref_t* s_screen_obj;

static js_ref_t* s_key_color;
static js_ref_t* s_key_content;
static js_ref_t* s_key_done;
static js_ref_t* s_key_get;
static js_ref_t* s_key_inBackground;
static js_ref_t* s_key_multisample;
static js_ref_t* s_key_priority;
static js_ref_t* s_key_set;
static js_ref_t* s_key_stack;
Expand Down Expand Up @@ -571,9 +573,11 @@ pegasus_init(int api_level)
s_api_level_nominal = SPHERE_API_LEVEL_STABLE;

s_key_color = jsal_new_key("color");
s_key_content = jsal_new_key("content");
s_key_done = jsal_new_key("done");
s_key_get = jsal_new_key("get");
s_key_inBackground = jsal_new_key("inBackground");
s_key_multisample = jsal_new_key("multisample");
s_key_priority = jsal_new_key("priority");
s_key_set = jsal_new_key("set");
s_key_stack = jsal_new_key("stack");
Expand Down Expand Up @@ -5177,6 +5181,7 @@ js_new_Texture(int num_args, bool is_ctor, intptr_t magic)
color_t fill_color;
int height;
image_t* image;
int multisample;
image_t* src_image;
int width;

Expand All @@ -5189,16 +5194,44 @@ js_new_Texture(int num_args, bool is_ctor, intptr_t magic)
height = jsal_require_int(1);
if (buffer_size < width * height * sizeof(color_t))
jsal_error(JS_RANGE_ERROR, "Not enough data in pixel buffer");
if (!(image = image_new(width, height, buffer)))
if (!(image = image_new(width, height, buffer, 0)))
jsal_error(JS_ERROR, "Couldn't create GPU texture");
}
else if (num_args >= 3 && s_api_level >= 4 && jsal_is_object_coercible(2)) {
// create an Image with additional options
width = jsal_require_int(0);
height = jsal_require_int(1);

if (jsal_get_prop_key(2, s_key_multisample))
multisample = jsal_require_int(-1);
else
multisample = 0;


if (jsal_get_prop_key(2, s_key_content)) {
buffer = jsal_require_buffer_ptr(-1, &buffer_size);
if (buffer_size < width * height * sizeof(color_t))
jsal_error(JS_RANGE_ERROR, "Not enough data in pixel buffer");
if (!(image = image_new(width, height, buffer, 0)))
jsal_error(JS_ERROR, "Couldn't create GPU texture");
}
else {
if (jsal_get_prop_key(2, s_key_color))
fill_color = jsal_pegasus_require_color(-1);
else
fill_color = mk_color(0, 0, 0, 0);
if (!(image = image_new(width, height, NULL, multisample)))
jsal_error(JS_ERROR, "Couldn't create GPU texture");
image_fill(image, fill_color, 1.0f);
}
}
else if (num_args >= 2) {
// create a Texture filled with a single pixel value
width = jsal_require_int(0);
height = jsal_require_int(1);
fill_color = num_args >= 3 ? jsal_pegasus_require_color(2)
: mk_color(0, 0, 0, 0);
if (!(image = image_new(width, height, NULL)))
if (!(image = image_new(width, height, NULL, 0)))
jsal_error(JS_ERROR, "Couldn't create GPU texture");
image_fill(image, fill_color, 1.0f);
}
Expand Down
4 changes: 2 additions & 2 deletions src/minisphere/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ screen_new(const char* title, image_t* icon, size2_t resolution, int frameskip,
// and the screen-grab functions.
al_store_state(&old_state, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_24_NO_ALPHA);
backbuffer = image_new(resolution.width, resolution.height, NULL);
backbuffer = image_new(resolution.width, resolution.height, NULL, 0);
al_restore_state(&old_state);
}
if (backbuffer == NULL) {
Expand Down Expand Up @@ -444,7 +444,7 @@ screen_grab(screen_t* it, int x, int y, int width, int height)
{
image_t* image;

if (!(image = image_new(width, height, NULL)))
if (!(image = image_new(width, height, NULL, 0)))
goto on_error;
image_render_to(image, NULL);
al_draw_bitmap_region(image_bitmap(it->backbuffer), x, y, width, height, 0, 0, 0x0);
Expand Down
2 changes: 1 addition & 1 deletion src/minisphere/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ fread_image(file_t* file, int width, int height)

console_log(3, "reading %dx%d image from open file", width, height);
file_pos = file_position(file);
if (!(image = image_new(width, height, NULL)))
if (!(image = image_new(width, height, NULL, 0)))
goto on_error;
if (!(lock = image_lock(image, true, false)))
goto on_error;
Expand Down
8 changes: 4 additions & 4 deletions src/minisphere/vanilla.c
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,7 @@ js_CreateSpriteset(int num_args, bool is_ctor, intptr_t magic)

spriteset = spriteset_new();
spriteset_set_base(spriteset, mk_rect(0, 0, width, height));
image = image_new(width, height, NULL);
image = image_new(width, height, NULL, 0);
for (i = 0; i < num_images; ++i) {
// use the same image in all slots to save memory. this works because
// images are read-only, so it doesn't matter that they all share the same
Expand Down Expand Up @@ -2126,7 +2126,7 @@ js_CreateSurface(int num_args, bool is_ctor, intptr_t magic)
height = jsal_to_int(1);
fill_color = num_args >= 3 ? jsal_require_sphere_color(2) : mk_color(0, 0, 0, 0);

if (!(image = image_new(width, height, NULL)))
if (!(image = image_new(width, height, NULL, 0)))
jsal_error(JS_ERROR, "Couldn't create GPU texture");
image_fill(image, fill_color, 1.0f);
jsal_push_class_obj(SV1_SURFACE, image, false);
Expand Down Expand Up @@ -8506,7 +8506,7 @@ js_Surface_cloneSection(int num_args, bool is_ctor, intptr_t magic)
width = jsal_to_int(2);
height = jsal_to_int(3);

if (!(new_image = image_new(width, height, NULL)))
if (!(new_image = image_new(width, height, NULL, 0)))
jsal_error(JS_ERROR, "couldn't create surface");
image_render_to(new_image, NULL);
al_clear_to_color(al_map_rgba(0, 0, 0, 0));
Expand Down Expand Up @@ -9045,7 +9045,7 @@ js_Surface_rotate(int num_args, bool is_ctor, intptr_t magic)
// FIXME: implement in-place resizing for Surface#rotate()
jsal_error(JS_ERROR, "Resizing not implemented for Surface#rotate()");
}
if (!(new_image = image_new(new_width, new_height, NULL)))
if (!(new_image = image_new(new_width, new_height, NULL, 0)))
jsal_error(JS_ERROR, "Couldn't create new surface");
image_render_to(new_image, NULL);
al_clear_to_color(al_map_rgba(0, 0, 0, 0));
Expand Down