Vala/杂波纹理加载线程
Vala/Clutter texture loading with thread
我试图在vala/杂波中加载图像文件,同时运行超时动画,使用"image。Set_load_async "在请求文件加载时暂停动画一段时间。这是来源:
// valac --thread --pkg clutter-1.0 --pkg=gio-2.0 test_1.vala -o test_1
using Clutter;
class SlideImage : Clutter.Actor {
protected Texture image = new Texture ();
public int loaded = 0;
public SlideImage (string file) {
try {
loaded = 1;
image.set_load_async (true);
image.load_finished.connect((t, a) => {
loaded = 2;
this.add_actor (image);
});
image.set_from_file (file);
} catch (Error e) {
warning("Error setting SlideImageReflected gradient : %s", e.message);
}
}
}
class ClutterSlideShow {
protected Stage stage;
protected int width = 800;
protected int height =700;
protected string[] file_names = {};
private int file_pointer = 0;
private int counter = 0;
private SlideImage showA = null;
private SlideImage showB = null;
private SlideImage showC = null;
private SlideImage showD = null;
private SlideImage showE = null;
public ClutterSlideShow (string folder) {
try {
var directory = File.new_for_path (folder);
var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0);
FileInfo file_info;
while ((file_info = enumerator.next_file ()) != null) {
file_names += folder+"/"+file_info.get_name ();
}
} catch (Error e) {
stderr.printf ("Error ClutterSlideShow listing files: %sn", e.message);
}
stage = Stage.get_default ();
stage.hide.connect (Clutter.main_quit);
stage.color = Color () { red = 0, green = 0, blue = 0, alpha = 255 };;
stage.set_size (width, height);
stage.show_all ();
}
protected string get_next_file () {
file_pointer++;
if (file_pointer > file_names.length) file_pointer = 1;
return file_names[file_pointer-1];
}
public void start () {
Timeout.add (15, run);
}
private bool run () {
if (showA == null) {
showA = new SlideImage (get_next_file ());
showA.set_x (0);
showA.set_y (0);
} else if (showA.loaded == 2) {
stage.add_actor (showA);
showA.loaded = 3;
} else if (showA.loaded == 3) {
showA.set_y (showA.get_y () + 1);
counter++;
if (counter==100) {
showB = new SlideImage (get_next_file ());
showB.set_x (100);
showB.set_y (0);
stage.add_actor (showB);
showC = new SlideImage (get_next_file ());
showC.set_x (200);
showC.set_y (0);
stage.add_actor (showC);
showD = new SlideImage (get_next_file ());
showD.set_x (300);
showD.set_y (0);
stage.add_actor (showD);
showE = new SlideImage (get_next_file ());
showE.set_x (400);
showE.set_y (0);
stage.add_actor (showE);
}
}
return true;
}
}
int main (string[] args) {
if (Thread.supported () == false) {
stderr.printf ("Threads are not supported!n");
return -1;
}
var result = init (ref args);
if (result != Clutter.InitError.SUCCESS) {
stderr.printf("Error: %sn", result.to_string());
return 1;
}
var slide_show = new ClutterSlideShow ("/usr/share/backgrounds/");
slide_show.start ();
Clutter.main ();
return 0;
}
我也尝试过使用"线程",但我得到了一个"分段错误(核心转储)",我不知道如何调试或修复。下面是示例:
// valac --thread --pkg clutter-1.0 --pkg=gio-2.0 test_2.vala -o test_2
using Clutter;
class SlideImage : Clutter.Actor {
protected Texture image = new Texture ();
public int loaded = 0;
public SlideImage (string file) {
loaded = 1;
load_image_in_background.begin(file, (obj, res) => {
try {
loaded = 2;
this.add_actor (image);
} catch (ThreadError e) {
string msg = e.message;
stderr.printf(@"Thread error: $msgn");
}
});
}
async void load_image_in_background (string file) throws ThreadError {
SourceFunc callback = load_image_in_background.callback;
ThreadFunc<void*> run = () => {
try {
// Help ! The next line results in "Segmentation fault"
image.set_from_file (file);
} catch (Error e) {
warning("Error setting SlideImage texture : %s", e.message);
}
Idle.add((owned) callback);
return null;
};
Thread.create<void*>(run, false);
yield;
}
}
class ClutterSlideShow {
protected Stage stage;
protected int width = 800;
protected int height =700;
protected string[] file_names = {};
private int file_pointer = 0;
private int counter = 0;
private SlideImage showA = null;
private SlideImage showB = null;
private SlideImage showC = null;
private SlideImage showD = null;
private SlideImage showE = null;
public ClutterSlideShow (string folder) {
try {
var directory = File.new_for_path (folder);
var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0);
FileInfo file_info;
while ((file_info = enumerator.next_file ()) != null) {
file_names += folder+"/"+file_info.get_name ();
}
} catch (Error e) {
stderr.printf ("Error ClutterSlideShow listing files: %sn", e.message);
}
stage = Stage.get_default ();
stage.hide.connect (Clutter.main_quit);
stage.color = Color () { red = 0, green = 0, blue = 0, alpha = 255 };;
stage.set_size (width, height);
stage.show_all ();
}
protected string get_next_file () {
file_pointer++;
if (file_pointer > file_names.length) file_pointer = 1;
return file_names[file_pointer-1];
}
public void start () {
Timeout.add (15, run);
}
private bool run () {
if (showA == null) {
showA = new SlideImage (get_next_file ());
showA.set_x (0);
showA.set_y (0);
} else if (showA.loaded == 2) {
stage.add_actor (showA);
showA.loaded = 3;
} else if (showA.loaded == 3) {
showA.set_y (showA.get_y () + 1);
counter++;
if (counter==100) {
showB = new SlideImage (get_next_file ());
showB.set_x (100);
showB.set_y (0);
stage.add_actor (showB);
showC = new SlideImage (get_next_file ());
showC.set_x (200);
showC.set_y (0);
stage.add_actor (showC);
showD = new SlideImage (get_next_file ());
showD.set_x (300);
showD.set_y (0);
stage.add_actor (showD);
showE = new SlideImage (get_next_file ());
showE.set_x (400);
showE.set_y (0);
stage.add_actor (showE);
}
}
return true;
}
}
int main (string[] args) {
if (Thread.supported () == false) {
stderr.printf ("Threads are not supported!n");
return -1;
}
var result = init (ref args);
if (result != Clutter.InitError.SUCCESS) {
stderr.printf("Error: %sn", result.to_string());
return 1;
}
var slide_show = new ClutterSlideShow ("/usr/share/backgrounds/");
slide_show.start ();
Clutter.main ();
return 0;
}
执行"stop"产生有两个原因:
- 文件加载(可以线程化)
- 图像/演员创建(不能线程化,但改进)
我得到了专家的帮助(感谢Victor),下一个代码改进了它:
- 线程文件加载
- 将图像缩放到最终的"杂波"大小
这是代码:
/**
* Build with:
* valac --thread --pkg clutter-1.0 --pkg gio-2.0 --pkg gdk-3.0 --target-glib=2.32 test_2.vala -o test_2
*/
const string SLIDESHOW_PATH = "/usr/share/backgrounds";
public class SlideImage : Clutter.Actor {
public bool ready { get; private set; default = false; }
private Clutter.Image image;
private Thread thread;
public SlideImage (File file, int width, int height) {
load_image_async.begin (file, width, height, (obj, res) => {
if (image == null)
return;
set_size (width, height);
set_content_scaling_filters (Clutter.ScalingFilter.TRILINEAR,
Clutter.ScalingFilter.LINEAR);
set_content_gravity (Clutter.ContentGravity.CENTER);
set_content (image);
ready = true;
});
}
private async void load_image_async (File file, int width, int height) {
var pixbuf = yield load_pixbuf_from_file_async (file);
if (pixbuf != null) {
image = new Clutter.Image ();
try {
float relation_w = pixbuf.get_width () / width;
float relation_h = pixbuf.get_height () / height;
float offset_x = 0.0f;
float offset_y = 0.0f;
float scale = 1.0f;
if (relation_w > relation_h) {
scale = (float) height / (float) pixbuf.get_height ();
if (pixbuf.get_width () > width)
offset_x = -((float) ((pixbuf.get_width () * scale) - width)) / 2.0f;
} else {
scale = (float) width / (float) pixbuf.get_width ();
if (pixbuf.get_height () > height)
offset_y = -((float) ((pixbuf.get_height () * scale) - height)) / 2.0f;
}
var pixbuf_scaled = new Gdk.Pixbuf (pixbuf.get_colorspace (),
pixbuf.get_has_alpha (),
pixbuf.get_bits_per_sample (),
width,
height);
pixbuf.scale (pixbuf_scaled, 0, 0, width, height, offset_x, offset_y, scale, scale, Gdk.InterpType.BILINEAR);
image.set_data (pixbuf_scaled.get_pixels (),
pixbuf_scaled.get_has_alpha () ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
pixbuf_scaled.get_width (),
pixbuf_scaled.get_height (),
pixbuf_scaled.get_rowstride ());
} catch (Error err) {
warning ("Could not set image from pixbuf: %s", err.message);
image = null;
}
}
}
private async Gdk.Pixbuf? load_pixbuf_from_file_async (File file) {
SourceFunc callback = load_pixbuf_from_file_async.callback;
Gdk.Pixbuf? pixbuf = null;
ThreadFunc<void*> thread_func = () => {
try {
pixbuf = new Gdk.Pixbuf.from_file (file.get_path ());
message ("loaded pixbuf");
} catch (Error e) {
warning ("Error loading pixbuf: %s", e.message);
}
Idle.add ((owned) callback);
return null;
};
thread = new Thread<void*> ("load-pixbuf-in-background", thread_func);
yield;
return pixbuf;
}
}
public class ClutterSlideShow {
private const int WIDTH = 800;
private const int HEIGHT = 600;
private int counter = 0;
private List<File> files;
private Clutter.Stage stage;
private SlideImage showA;
private SlideImage showB;
private SlideImage showC;
private SlideImage showD;
private SlideImage showE;
public ClutterSlideShow (string folder) {
load_files (File.new_for_path (folder));
init_stage ();
}
public void start () {
Timeout.add (15, run);
}
protected File? get_next_file () {
var file = files.nth_data (0);
if (file != null)
files.remove (file);
return file;
}
private void load_files (File directory) {
files = new List<File> ();
try {
var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME,0);
FileInfo file_info;
while ((file_info = enumerator.next_file ()) != null) {
var child_file = directory.get_child (file_info.get_name ());
files.prepend (child_file);
}
} catch (Error e) {
warning (e.message);
}
}
private void init_stage () {
stage = new Clutter.Stage ();
stage.background_color = Clutter.Color () { red = 0, green = 0, blue = 0, alpha = 255 };
stage.set_size (WIDTH, HEIGHT);
stage.show ();
stage.hide.connect (Clutter.main_quit);
}
private bool run () {
if (showA == null) {
showA = new SlideImage (get_next_file (), 400, 400);
showA.x = 0;
showA.y = 0;
} else if (showA.get_parent () != stage) {
stage.add_child (showA);
} else if (showA.ready) {
showA.set_y (showA.get_y () + 1);
counter++;
if (counter == 50) {
showB = new SlideImage (get_next_file (), 400, 400);
showB.set_x (100);
showB.set_y (0);
stage.add_child (showB);
showC = new SlideImage (get_next_file (), 400, 400);
showC.set_x (200);
showC.set_y (0);
stage.add_child (showC);
showD = new SlideImage (get_next_file (), 400, 400);
showD.set_x (300);
showD.set_y (0);
stage.add_child (showD);
showE = new SlideImage (get_next_file (), 400, 400);
showE.set_x (400);
showE.set_y (0);
stage.add_child (showE);
}
}
return true;
}
}
void main (string[] args) {
var result = Clutter.init (ref args);
if (result != Clutter.InitError.SUCCESS)
error ("Failed to init clutter: %s", result.to_string ());
var slide_show = new ClutterSlideShow (SLIDESHOW_PATH);
slide_show.start ();
Clutter.main ();
}
相关文章:
- C++ 多线程原子加载/存储
- 是否可以在跨内核线程迁移后强制重新加载 thread_local 变量?
- OpenGL 在与呈现线程不同的线程中创建和加载 VBO 信息
- 加载的 OpenGL 函数是特定于上下文还是特定于线程?(视窗)
- 如何在单独的线程上加载纹理到主内存并使用它在另一个线程上渲染
- C++线程进行后台加载
- Valgrind:在多线程程序中发现冲突的存储/加载
- COCOS2D-X:从另一个线程中加载精灵,任何模式
- STD ::线程访问从共享库加载的函数
- Qt:在另一个线程中预加载 qpixmap
- 线程加载图像的速度更快,直到它们在Studio中消失
- SDL2加载屏幕/线程
- 在加载 DLL 之前创建远程线程
- Valgrind:getter方法中包含rdlock的线程加载冲突
- 正在加载一批图像-线程分配
- Vala/杂波纹理加载线程
- 使用memory_order_relax来加载原子变量是否安全,如果只有一个线程对该变量进行写操作
- 在DLL中使用新的Vista线程池API也可以在XP中加载(在XP中不使用线程池代码)
- c++中的多线程:加载一个大文件并执行一个函数
- 如何使用cmake和Android NDK在C++中加载线程支持