7 #include "evas_gl_common.h"
13 #include "evas_common.h"
14 #include "evas_private.h"
15 #include "evas_engine.h"
16 #include "Evas_Engine_GL_X11.h"
19 /* function tables - filled in later (func and parent func) */
20 static Evas_Func func, pfunc;
22 static Visual *eng_best_visual_get(Display *disp, int screen);
23 static Colormap eng_best_colormap_get(Display *disp, int screen);
24 static int eng_best_depth_get(Display *disp, int screen);
26 typedef struct _Render_Engine Render_Engine;
30 Evas_GL_X11_Window *win;
37 Evas_Engine_Info_GL_X11 *info;
39 info = calloc(1, sizeof(Evas_Engine_Info_GL_X11));
40 if (!info) return NULL;
41 info->magic.magic = rand();
42 info->func.best_visual_get = eng_best_visual_get;
43 info->func.best_colormap_get = eng_best_colormap_get;
44 info->func.best_depth_get = eng_best_depth_get;
50 eng_info_free(Evas *e, void *info)
52 Evas_Engine_Info_GL_X11 *in;
54 in = (Evas_Engine_Info_GL_X11 *)info;
59 eng_setup(Evas *e, void *in)
62 Evas_Engine_Info_GL_X11 *info;
65 info = (Evas_Engine_Info_GL_X11 *)in;
66 if (!e->engine.data.output)
68 if (!glXQueryExtension(info->info.display, &eb, &evb)) return;
69 re = calloc(1, sizeof(Render_Engine));
71 e->engine.data.output = re;
72 re->win = eng_window_new(info->info.display,
74 0 /* FIXME: screen 0 assumption */,
83 e->engine.data.output = NULL;
87 evas_common_cpu_init();
89 evas_common_blend_init();
90 evas_common_image_init();
91 evas_common_convert_init();
92 evas_common_scale_init();
93 evas_common_rectangle_init();
94 evas_common_gradient_init();
95 evas_common_polygon_init();
96 evas_common_line_init();
97 evas_common_font_init();
98 evas_common_draw_init();
99 evas_common_tilebuf_init();
103 re = e->engine.data.output;
104 eng_window_free(re->win);
105 re->win = eng_window_new(info->info.display,
107 0,/* FIXME: screen 0 assumption */
114 if (!e->engine.data.output) return;
115 if (!e->engine.data.context)
116 e->engine.data.context =
117 e->engine.func->context_new(e->engine.data.output);
121 eng_output_free(void *data)
125 re = (Render_Engine *)data;
126 eng_window_free(re->win);
129 evas_common_font_shutdown();
130 evas_common_image_shutdown();
134 eng_output_resize(void *data, int w, int h)
138 re = (Render_Engine *)data;
141 evas_gl_common_context_resize(re->win->gl_context, w, h);
145 eng_output_tile_size_set(void *data, int w, int h)
149 re = (Render_Engine *)data;
153 eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
157 re = (Render_Engine *)data;
158 evas_gl_common_context_resize(re->win->gl_context, re->win->w, re->win->h);
159 /* smple bounding box */
160 if (!re->win->draw.redraw)
163 re->win->draw.x1 = x;
164 re->win->draw.y1 = y;
165 re->win->draw.x2 = x + w - 1;
166 re->win->draw.y2 = y + h - 1;
168 re->win->draw.x1 = 0;
169 re->win->draw.y1 = 0;
170 re->win->draw.x2 = re->win->w - 1;
171 re->win->draw.y2 = re->win->h - 1;
176 if (x < re->win->draw.x1) re->win->draw.x1 = x;
177 if (y < re->win->draw.y1) re->win->draw.y1 = y;
178 if ((x + w - 1) > re->win->draw.x2) re->win->draw.x2 = x + w - 1;
179 if ((y + h - 1) > re->win->draw.y2) re->win->draw.y2 = y + h - 1;
181 re->win->draw.redraw = 1;
185 eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
189 re = (Render_Engine *)data;
193 eng_output_redraws_clear(void *data)
197 re = (Render_Engine *)data;
198 re->win->draw.redraw = 0;
199 // printf("GL: finish update cycle!\n");
202 /* at least the nvidia drivers are so abysmal that copying from the backbuffer
203 * to the front using glCopyPixels() that you literally can WATCH it draw the
204 * pixels slowly across the screen with a window update taking multiple
205 * seconds - so workaround by doing a full buffer render as frankly GL isn't
206 * up to doing anything that isn't done by quake (etc.)
208 #define SLOW_GL_COPY_RECT 1
209 /* vsync games - not for now though */
210 //#define VSYNC_TO_SCREEN 1
213 eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
217 re = (Render_Engine *)data;
218 /* get the upate rect surface - return engine data as dummy */
219 if (!re->win->draw.redraw)
221 // printf("GL: NO updates!\n");
224 // printf("GL: update....!\n");
225 #ifdef SLOW_GL_COPY_RECT
226 /* if any update - just return the whole canvas - works with swap
230 if (w) *w = re->win->w;
231 if (h) *h = re->win->h;
234 if (cw) *cw = re->win->w;
235 if (ch) *ch = re->win->h;
237 /* 1 update - INCREDIBLY SLOW if combined with swap_rect in flush. a gl
238 * problem where there just is no hardware path for somethnig that
239 * obviously SHOULD be there */
240 /* only 1 update to minimise gl context games and rendering multiple update
241 * regions as evas does with other engines
243 if (x) *x = re->win->draw.x1;
244 if (y) *y = re->win->draw.y1;
245 if (w) *w = re->win->draw.x2 - re->win->draw.x1 + 1;
246 if (h) *h = re->win->draw.y2 - re->win->draw.y1 + 1;
247 if (cx) *cx = re->win->draw.x1;
248 if (cy) *cy = re->win->draw.y1;
249 if (cw) *cw = re->win->draw.x2 - re->win->draw.x1 + 1;
250 if (ch) *ch = re->win->draw.y2 - re->win->draw.y1 + 1;
256 eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
260 re = (Render_Engine *)data;
261 /* put back update surface.. in this case just unflag redraw */
262 // printf("GL: update done.\n");
263 re->win->draw.redraw = 0;
264 re->win->draw.drew = 1;
268 eng_output_flush(void *data)
272 re = (Render_Engine *)data;
273 if (!re->win->draw.drew) return;
274 re->win->draw.drew = 0;
275 // printf("GL: flush your mush!\n");
276 eng_window_use(re->win);
278 #ifdef VSYNC_TO_SCREEN
283 glXGetVideoSyncSGI(&rc);
284 glXWaitVideoSyncSGI(2, (rc + 1) % 2, &rc);
287 #ifdef SLOW_GL_COPY_RECT
288 glXSwapBuffers(re->win->disp, re->win->win);
290 /* SLOW AS ALL HELL! */
291 evas_gl_common_swap_rect(re->win->gl_context,
292 re->win->draw.x1, re->win->draw.y1,
293 re->win->draw.x2 - re->win->draw.x1 + 1,
294 re->win->draw.y2 - re->win->draw.y1 + 1);
298 // XSync(re->win->disp, False);
299 // printf("SYNC! %i\n", fr++);
303 eng_output_idle_flush(void *data)
307 re = (Render_Engine *)data;
311 eng_context_cutout_add(void *data, void *context, int x, int y, int w, int h)
315 re = (Render_Engine *)data;
316 /* not used in gl engine */
320 eng_context_cutout_clear(void *data, void *context)
324 re = (Render_Engine *)data;
325 /* not used in gl engine */
329 eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
333 re = (Render_Engine *)data;
334 eng_window_use(re->win);
335 re->win->gl_context->dc = context;
336 evas_gl_common_rect_draw(re->win->gl_context, x, y, w, h);
340 eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2)
344 re = (Render_Engine *)data;
345 re->win->gl_context->dc = context;
346 evas_gl_common_line_draw(re->win->gl_context, x1, y1, x2, y2);
350 eng_polygon_point_add(void *data, void *context, void *polygon, int x, int y)
354 re = (Render_Engine *)data;
355 return evas_gl_common_poly_point_add(polygon, x, y);
360 eng_polygon_points_clear(void *data, void *context, void *polygon)
364 re = (Render_Engine *)data;
365 return evas_gl_common_poly_points_clear(polygon);
369 eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
373 re = (Render_Engine *)data;
374 re->win->gl_context->dc = context;
375 evas_gl_common_poly_draw(re->win->gl_context, polygon);
379 eng_gradient_new(void *data)
381 return evas_gl_common_gradient_new();
385 eng_gradient_color_stop_add(void *data, void *gradient, int r, int g, int b, int a, int delta)
387 evas_gl_common_gradient_color_stop_add(gradient, r, g, b, a, delta);
391 eng_gradient_alpha_stop_add(void *data, void *gradient, int a, int delta)
393 evas_gl_common_gradient_alpha_stop_add(gradient, a, delta);
397 eng_gradient_clear(void *data, void *gradient)
399 evas_gl_common_gradient_clear(gradient);
403 eng_gradient_color_data_set(void *data, void *gradient, void *map, int len, int has_alpha)
405 evas_gl_common_gradient_color_data_set(gradient, map, len, has_alpha);
409 eng_gradient_alpha_data_set(void *data, void *gradient, void *alpha_map, int len)
411 evas_gl_common_gradient_alpha_data_set(gradient, alpha_map, len);
415 eng_gradient_free(void *data, void *gradient)
417 evas_gl_common_gradient_free(gradient);
421 eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h)
423 evas_gl_common_gradient_fill_set(gradient, x, y, w, h);
427 eng_gradient_fill_angle_set(void *data, void *gradient, double angle)
429 evas_gl_common_gradient_fill_angle_set(gradient, angle);
433 eng_gradient_fill_spread_set(void *data, void *gradient, int spread)
435 evas_gl_common_gradient_fill_spread_set(gradient, spread);
439 eng_gradient_angle_set(void *data, void *gradient, double angle)
441 evas_gl_common_gradient_map_angle_set(gradient, angle);
445 eng_gradient_offset_set(void *data, void *gradient, float offset)
447 evas_gl_common_gradient_map_offset_set(gradient, offset);
451 eng_gradient_direction_set(void *data, void *gradient, int direction)
453 evas_gl_common_gradient_map_direction_set(gradient, direction);
457 eng_gradient_type_set(void *data, void *gradient, char *name, char *params)
459 evas_gl_common_gradient_type_set(gradient, name, params);
463 eng_gradient_is_opaque(void *data, void *context, void *gradient, int x, int y, int w, int h)
465 Render_Engine *re = (Render_Engine *)data;
467 re->win->gl_context->dc = context;
468 return evas_gl_common_gradient_is_opaque(re->win->gl_context, gradient, x, y, w, h);
472 eng_gradient_is_visible(void *data, void *context, void *gradient, int x, int y, int w, int h)
474 Render_Engine *re = (Render_Engine *)data;
476 re->win->gl_context->dc = context;
477 return evas_gl_common_gradient_is_visible(re->win->gl_context, gradient, x, y, w, h);
481 eng_gradient_render_pre(void *data, void *context, void *gradient)
483 Render_Engine *re = (Render_Engine *)data;
485 re->win->gl_context->dc = context;
486 evas_gl_common_gradient_render_pre(re->win->gl_context, gradient);
490 eng_gradient_render_post(void *data, void *gradient)
492 evas_gl_common_gradient_render_post(gradient);
496 eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h)
500 re = (Render_Engine *)data;
501 eng_window_use(re->win);
502 re->win->gl_context->dc = context;
503 evas_gl_common_gradient_draw(re->win->gl_context, gradient, x, y, w, h);
507 eng_image_alpha_get(void *data, void *image)
512 re = (Render_Engine *)data;
513 if (!image) return 1;
515 /* FIXME: can move to gl_common */
516 switch (im->cs.space)
518 case EVAS_COLORSPACE_ARGB8888:
519 if (im->im->cache_entry.flags.alpha) return 1;
527 eng_image_colorspace_get(void *data, void *image)
532 re = (Render_Engine *)data;
533 if (!image) return EVAS_COLORSPACE_ARGB8888;
539 eng_image_alpha_set(void *data, void *image, int has_alpha)
544 re = (Render_Engine *)data;
545 if (!image) return NULL;
546 eng_window_use(re->win);
548 /* FIXME: can move to gl_common */
549 if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im;
550 if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image;
551 else if ((!has_alpha) && (!im->im->cache_entry.flags.alpha)) return image;
552 if (im->references > 1)
554 Evas_GL_Image *im_new;
556 im_new = evas_gl_common_image_new_from_copied_data(im->gc, im->im->cache_entry.w, im->im->cache_entry.h, im->im->image.data,
557 eng_image_alpha_get(data, image),
558 eng_image_colorspace_get(data, image));
559 if (!im_new) return im;
560 evas_gl_common_image_free(im);
564 evas_gl_common_image_dirty(im);
565 im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0;
570 eng_image_border_set(void *data, void *image, int l, int r, int t, int b)
574 re = (Render_Engine *)data;
579 eng_image_border_get(void *data, void *image, int *l, int *r, int *t, int *b)
583 re = (Render_Engine *)data;
587 eng_image_comment_get(void *data, void *image, char *key)
592 re = (Render_Engine *)data;
593 if (!image) return NULL;
595 return im->im->info.comment;
599 eng_image_format_get(void *data, void *image)
604 re = (Render_Engine *)data;
610 eng_image_colorspace_set(void *data, void *image, int cspace)
615 re = (Render_Engine *)data;
618 /* FIXME: can move to gl_common */
619 if (im->cs.space == cspace) return;
620 evas_cache_image_colorspace(&im->im->cache_entry, cspace);
623 case EVAS_COLORSPACE_ARGB8888:
626 if (!im->cs.no_free) free(im->cs.data);
631 case EVAS_COLORSPACE_YCBCR422P601_PL:
632 case EVAS_COLORSPACE_YCBCR422P709_PL:
633 if (im->tex) evas_gl_common_texture_free(im->tex);
637 if (!im->cs.no_free) free(im->cs.data);
639 im->cs.data = calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2);
646 im->cs.space = cspace;
650 eng_image_native_set(void *data, void *image, void *native)
655 eng_image_native_get(void *data, void *image)
661 eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
665 re = (Render_Engine *)data;
667 eng_window_use(re->win);
668 return evas_gl_common_image_load(re->win->gl_context, file, key, lo);
672 eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
676 re = (Render_Engine *)data;
677 eng_window_use(re->win);
678 return evas_gl_common_image_new_from_data(re->win->gl_context, w, h, image_data, alpha, cspace);
682 eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
686 re = (Render_Engine *)data;
687 eng_window_use(re->win);
688 return evas_gl_common_image_new_from_copied_data(re->win->gl_context, w, h, image_data, alpha, cspace);
692 eng_image_free(void *data, void *image)
696 re = (Render_Engine *)data;
698 eng_window_use(re->win);
699 evas_gl_common_image_free(image);
703 eng_image_size_get(void *data, void *image, int *w, int *h)
707 re = (Render_Engine *)data;
714 if (w) *w = ((Evas_GL_Image *)image)->im->cache_entry.w;
715 if (h) *h = ((Evas_GL_Image *)image)->im->cache_entry.h;
719 eng_image_size_set(void *data, void *image, int w, int h)
722 Evas_GL_Image *im, *im_old;
724 re = (Render_Engine *)data;
725 if (!image) return NULL;
726 eng_window_use(re->win);
728 if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) ||
729 (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL))
731 if ((im_old) && (im_old->im->cache_entry.w == w) && (im_old->im->cache_entry.h == h))
735 im = evas_gl_common_image_new(re->win->gl_context, w, h,
736 eng_image_alpha_get(data, image),
737 eng_image_colorspace_get(data, image));
739 evas_common_load_image_data_from_file(im_old->im);
740 if (im_old->im->image->data)
742 evas_common_blit_rectangle(im_old->im, im->im, 0, 0, w, h, 0, 0);
743 evas_common_cpu_end_opt();
746 evas_gl_common_image_free(im_old);
749 im = evas_gl_common_image_new(re->win->gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888);
754 eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
758 re = (Render_Engine *)data;
759 if (!image) return NULL;
760 evas_gl_common_image_dirty(image);
765 eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data)
770 re = (Render_Engine *)data;
777 eng_window_use(re->win);
778 evas_cache_image_load_data(&im->im->cache_entry);
779 switch (im->cs.space)
781 case EVAS_COLORSPACE_ARGB8888:
784 if (im->references > 1)
786 Evas_GL_Image *im_new;
788 im_new = evas_gl_common_image_new_from_copied_data(im->gc, im->im->cache_entry.w, im->im->cache_entry.h, im->im->image.data,
789 eng_image_alpha_get(data, image),
790 eng_image_colorspace_get(data, image));
796 evas_gl_common_image_free(im);
800 evas_gl_common_image_dirty(im);
802 *image_data = im->im->image.data;
804 case EVAS_COLORSPACE_YCBCR422P601_PL:
805 case EVAS_COLORSPACE_YCBCR422P709_PL:
806 *image_data = im->cs.data;
816 eng_image_data_put(void *data, void *image, DATA32 *image_data)
819 Evas_GL_Image *im, *im2;
821 re = (Render_Engine *)data;
822 if (!image) return NULL;
824 eng_window_use(re->win);
825 switch (im->cs.space)
827 case EVAS_COLORSPACE_ARGB8888:
828 if (image_data != im->im->image.data)
832 w = im->im->cache_entry.w;
833 h = im->im->cache_entry.h;
834 im2 = eng_image_new_from_data(data, w, h, image_data,
835 eng_image_alpha_get(data, image),
836 eng_image_colorspace_get(data, image));
838 evas_gl_common_image_free(im);
842 case EVAS_COLORSPACE_YCBCR422P601_PL:
843 case EVAS_COLORSPACE_YCBCR422P709_PL:
844 if (image_data != im->cs.data)
848 if (!im->cs.no_free) free(im->cs.data);
850 im->cs.data = image_data;
857 /* hmmm - but if we wrote... why bother? */
858 evas_gl_common_image_dirty(im);
863 eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
867 re = (Render_Engine *)data;
869 eng_window_use(re->win);
870 re->win->gl_context->dc = context;
871 evas_gl_common_image_draw(re->win->gl_context, image,
872 src_x, src_y, src_w, src_h,
873 dst_x, dst_y, dst_w, dst_h,
878 eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
882 re = (Render_Engine *)data;
884 static RGBA_Image *im = NULL;
887 im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
888 evas_cache_image_surface_alloc(&im->cache_entry, re->win->w, re->win->h);
890 evas_common_draw_context_font_ext_set(context,
892 evas_gl_font_texture_new,
893 evas_gl_font_texture_free,
894 evas_gl_font_texture_draw);
895 evas_common_font_draw(im, context, font, x, y, text);
896 evas_common_draw_context_font_ext_set(context,
904 /* private engine functions the calling prog can use */
907 eng_best_visual_get(Display *disp, int screen)
909 if (!disp) return NULL;
910 if (!_evas_gl_x11_vi)
911 _evas_gl_x11_vi = glXChooseVisual(disp, screen,
912 _evas_gl_x11_configuration);
913 if (!_evas_gl_x11_vi) return NULL;
914 return _evas_gl_x11_vi->visual;
918 eng_best_colormap_get(Display *disp, int screen)
921 if (!_evas_gl_x11_vi)
922 eng_best_visual_get(disp, screen);
923 if (!_evas_gl_x11_vi) return 0;
924 _evas_gl_x11_cmap = XCreateColormap(disp, RootWindow(disp, screen),
925 _evas_gl_x11_vi->visual, 0);
926 return _evas_gl_x11_cmap;
930 eng_best_depth_get(Display *disp, int screen)
933 if (!_evas_gl_x11_vi)
934 eng_best_visual_get(disp, screen);
935 if (!_evas_gl_x11_vi) return 0;
936 return _evas_gl_x11_vi->depth;
940 module_open(Evas_Module *em)
943 /* get whatever engine module we inherit from */
944 if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
945 /* store it for later use */
947 /* now to override methods */
948 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
954 ORD(output_tile_size_set);
955 ORD(output_redraws_rect_add);
956 ORD(output_redraws_rect_del);
957 ORD(output_redraws_clear);
958 ORD(output_redraws_next_update_get);
959 ORD(output_redraws_next_update_push);
960 ORD(context_cutout_add);
961 ORD(context_cutout_clear);
963 ORD(output_idle_flush);
966 ORD(polygon_point_add);
967 ORD(polygon_points_clear);
971 ORD(gradient_color_stop_add);
972 ORD(gradient_alpha_stop_add);
973 ORD(gradient_color_data_set);
974 ORD(gradient_alpha_data_set);
976 ORD(gradient_fill_set);
977 ORD(gradient_fill_angle_set);
978 ORD(gradient_fill_spread_set);
979 ORD(gradient_angle_set);
980 ORD(gradient_offset_set);
981 ORD(gradient_direction_set);
982 ORD(gradient_type_set);
983 ORD(gradient_is_opaque);
984 ORD(gradient_is_visible);
985 ORD(gradient_render_pre);
986 ORD(gradient_render_post);
989 ORD(image_new_from_data);
990 ORD(image_new_from_copied_data);
994 ORD(image_dirty_region);
997 ORD(image_alpha_set);
998 ORD(image_alpha_get);
999 ORD(image_border_set);
1000 ORD(image_border_get);
1002 ORD(image_comment_get);
1003 ORD(image_format_get);
1004 ORD(image_colorspace_set);
1005 ORD(image_colorspace_get);
1006 ORD(image_native_set);
1007 ORD(image_native_get);
1009 /* now advertise out own api */
1010 em->functions = (void *)(&func);
1020 EAPI Evas_Module_Api evas_modapi =
1022 EVAS_MODULE_API_VERSION,
1023 EVAS_MODULE_TYPE_ENGINE,