aboutsummaryrefslogtreecommitdiff
path: root/src/render.c
blob: 528d7754ce8026975bd24d6e7bae830eb37a7473 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * render.c
 *
 *  Created on: 15.01.2018
 *      Author: Superleo1810
 */

#include "render.h"
#define HAVE_STRUCT_TIMESPEC
#include <pthread.h>

void render_init(Config *config, u32 (*sfunc) (double, double, u32))
{
	_config = config;
	_sfunc = sfunc;

	ui_render.window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
	gtk_window_set_default_size(ui_render.window, config->width, config->height);

	ui_render.frame = GTK_FRAME(gtk_frame_new(NULL));
	gtk_container_add(GTK_CONTAINER(ui_render.window), ui_render.frame);

	ui_render.drawing_area = GTK_DRAWING_AREA(gtk_drawing_area_new());
	gtk_widget_set_size_request(GTK_WIDGET(ui_render.drawing_area), config->width, config->height);
	g_signal_connect(G_OBJECT(ui_render.drawing_area), "draw", G_CALLBACK(on_draw), NULL);
	gtk_container_add(GTK_CONTAINER(ui_render.frame), ui_render.drawing_area);

}

void render_show()
{
	gtk_widget_show_all(GTK_WIDGET(ui_render.window));
}

void on_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
{
	cairo_surface_t *image;
	// TODO: MUSS UNBEDINGT SEPARAT GECALLT WERDEN, SONST KEINE 60 FPS
	image = render_surface();
	cairo_set_source_surface(cr, image, 0, 0);
	cairo_paint(cr);
}

struct arg_thread {
	cairo_surface_t *result;
	unsigned short threadCount;
	unsigned short threadNumber;
	unsigned char *current_row;
};

void *imageCalcThread(void *arguments)
{


	struct arg_thread *args = arguments;
	cairo_surface_t *result = args->result;
	unsigned int threadCount = args->threadCount;
	unsigned int threadNumber = args->threadNumber;
	unsigned char *current_row = args->current_row;



	int stride;
	double x_math, y_math;
	u32 iterations;

	printf("thread calculating %s",result);
	current_row = cairo_image_surface_get_data(result);
	stride = cairo_image_surface_get_stride(result);


	//Calculating start and endpoint for current thread to calculate
	int startingPoint = (_config->height/threadCount)*(threadNumber);
	int endPoint = ((_config->height/threadCount)*(threadNumber + 1)) - 1;


	for (int y = startingPoint; y < endPoint && y < _config->height; y++) {
		u32 *row = (void *) current_row;
		for (int x = 0; x < _config->width; x++) {
			x_math = /*x_MIN*/-2.0 + ((double) x * (/*x_MAX*/1.0 - /*x_MIN*/-2.0)) / _config->width;
			y_math = /*y_MIN*/-1.0 + ((double) (_config->height - y) * (/*y_MAX*/1.0 - /*y_MIN*/-1.0)) / _config->height;
			iterations = _sfunc(x_math, y_math, _config->iterations);
			row[x] = (((1<<24)-1)*iterations)/_config->iterations;
//            if (iterations > 1<<8)
//            	printf("schon gruen\n");
		}

		current_row += stride;
	}

}

cairo_surface_t *render_surface()
{
    cairo_surface_t *result;
    unsigned short threadCount = 4;
    unsigned char *current_row;

	result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, _config->width, _config->height);
		if (cairo_surface_status(result) != CAIRO_STATUS_SUCCESS)
			return result;

    cairo_surface_flush(result);



    //initialize thread related values and put them into a struct, as just one parameter is passed
    struct arg_thread args;
    args.result = result;
    args.threadCount = threadCount;
    args.current_row = current_row;

    pthread_t tid;

    //Create threads up to the number specified in threadCount
    for (int i = 0; i < threadCount; i++){
    	   args.threadNumber = i;
           pthread_create(&tid, NULL, imageCalcThread, (void *)&args);
    }

    //Wait for threads to finish and continue with the program
    pthread_join(tid,NULL);

    cairo_surface_mark_dirty(result);
    return result;
}