diff --git a/legacy/evas/src/Makefile.am b/legacy/evas/src/Makefile.am index d18f34bf92..b351ebc884 100644 --- a/legacy/evas/src/Makefile.am +++ b/legacy/evas/src/Makefile.am @@ -20,6 +20,7 @@ libevas_la_SOURCES = \ evas_bits.c \ evas_callbacks.c \ evas_events.c \ +evas_gl_routines.c \ evas_gradient.c \ evas_image.c \ evas_line.c \ @@ -32,6 +33,6 @@ evas_render.c \ evas_text.c \ Evas.h -libevas_la_LIBADD = -lX11 -lXext -lttf -ldl -lm -lImlib2 -ldb $(LDFLAGS) +libevas_la_LIBADD = -lX11 -lXext -lttf -ldl -lm -lImlib2 -ldb -lGL $(LDFLAGS) libevas_la_DEPENDENCIES = $(top_builddir)/config.h libevas_la_LDFLAGS = -version-info 0:1:0 diff --git a/legacy/evas/src/evas_gl_routines.c b/legacy/evas/src/evas_gl_routines.c new file mode 100644 index 0000000000..9806531855 --- /dev/null +++ b/legacy/evas/src/evas_gl_routines.c @@ -0,0 +1,411 @@ +/* C library header files. */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "Evas.h" + +Display *disp; + +static int __evas_gl_configuration[] = +{ + GLX_DOUBLEBUFFER, + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None +}; + +/* imlib 2 opengl backend work - transfer imlib image between states */ +/* of being client-side data, a texture set (an WxH array of textutes */ +/* tiled - to work around maximum texture size limitation of opengl) and */ +/* a buffer (using a pixmap as a destination drawable so we can render */ +/* ofscreen) */ + +typedef struct _evas_gl_image Evas_GL_Image; +typedef enum _evas_gl_image_state Evas_GL_Image_State; + +enum _evas_gl_image_state +{ + EVAS_STATE_DATA, + EVAS_STATE_TEXTURE +}; + +struct _evas_gl_image +{ + Evas_GL_Image_State state; + int w, h; +/* data specific params */ + DATA32 *data; +/* common GL params */ + GLXContext context; +/* texture state specific params */ + struct _tex + { + int max_size; + int w, h; + int edge_w, edge_h; + GLuint *textures; + } texture; +/* buffer specific params */ + struct _buf + { + Display *display; + XVisualInfo *visual_info; + Colormap colormap; + Window window; + } buffer; +}; + +void +__evas_gl_copy_image_rect_to_texture(Evas_GL_Image *im, int x, int y, + int w, int h, int tw, int th, + GLuint texture) +{ + int tx, ty; + DATA32 *data, *p1, *p2; + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + data = malloc(tw * th * 4); + for (ty = 0; ty < h; ty++) + { + p1 = im->data + ((y + ty) * im->w) + x; + p2 = data + (ty * tw); + for (tx = 0; tx < w; tx++) + { + *p2 = + ((*p1 & 0xff000000)) | + ((*p1 & 0x00ff0000) >> 16) | + ((*p1 & 0x0000ff00)) | + ((*p1 & 0x000000ff) << 16); + p2++; p1++; + } + + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + free(data); +} + +void +__evas_gl_move_state_data_to_texture(Evas_GL_Image *im) +{ + int i, x, y; + XSetWindowAttributes att; + + if (!im->data) return; + + im->texture.w = im->w / (im->texture.max_size - 2); + if (im->w > ((im->texture.max_size - 2) * im->texture.w)) + { + int shift = 0; + + im->texture.edge_w = im->w - (im->texture.w * (im->texture.max_size - 2)); + while (im->texture.edge_w < (im->texture.max_size >> shift)) shift++; + im->texture.edge_w = im->texture.max_size >> (shift - 1); + im->texture.w++; + } + else + im->texture.edge_w = im->texture.max_size; + im->texture.h = im->h / (im->texture.max_size - 2); + if (im->h > ((im->texture.max_size - 2) * im->texture.h)) + { + int shift = 0; + + im->texture.edge_h = im->h - (im->texture.h * (im->texture.max_size - 2)); + while (im->texture.edge_h < (im->texture.max_size >> shift)) shift++; + im->texture.edge_h = im->texture.max_size >> (shift - 1); + im->texture.h++; + } + else + im->texture.edge_h = im->texture.max_size; + + att.colormap = im->buffer.colormap; + att.border_pixel = 0; + att.event_mask = 0; + im->buffer.window = XCreateWindow(im->buffer.display, + RootWindow(disp, DefaultScreen(disp)), + 0, 0, 32, 32, 0, + im->buffer.visual_info->depth, + InputOutput, + im->buffer.visual_info->visual, + CWColormap | CWBorderPixel | CWEventMask, + &att); + im->texture.textures = malloc(sizeof(GLuint) * im->texture.w * im->texture.h); + glXMakeCurrent(im->buffer.display, im->buffer.window, im->context); + glGenTextures(im->texture.w * im->texture.h, im->texture.textures); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glEnable(GL_TEXTURE_2D); + + for (i = 0, y = 0; y < im->texture.h; y++) + { + for (x = 0; x < im->texture.w; x++, i++) + { + int xx, yy, ww, hh, tw, th; + + if (x == (im->texture.w - 1)) tw = im->texture.edge_w; + else tw = im->texture.max_size; + if (y == (im->texture.h - 1)) th = im->texture.edge_h; + else th = im->texture.max_size; + + if (x == 0) xx = 0; + else xx = x * (im->texture.max_size - 2) - 1; + if (x == (im->texture.w - 1)) ww = im->w - (x * (im->texture.max_size- 2)); + else ww = im->texture.max_size - 2; + ww += 2; + if (x == 0) ww--; + if (x == (im->texture.w - 1)) ww--; + + if (y == 0) yy = 0; + else yy = y * (im->texture.max_size - 2) - 1; + if (y == (im->texture.h - 1)) hh = im->h - (y * (im->texture.max_size- 2)); + else hh = im->texture.max_size - 2; + hh += 2; + if (y == 0) hh--; + if (y == (im->texture.h - 1)) hh--; + + __evas_gl_copy_image_rect_to_texture(im, xx, yy, ww, hh, tw, th, + im->texture.textures[i]); + } + } + /* done - set the actual image state to textured */ + im->state = EVAS_STATE_TEXTURE; +} + +void __evas_calc_tex_and_poly(Evas_GL_Image *im, int x, double *x1, double *x2, + int *tx, int *txx, double *dtx, double *dtxx, int tw, int w, int edge) +{ + if ((x == 0) && (tw > 1)) + { + *tx = 0; + *txx = im->texture.max_size - 2; + *dtx = (double)*tx / (im->texture.max_size); + *dtxx = (double)*txx / (im->texture.max_size); + } + else if (x < (tw - 1)) + { + *tx = 1; + *txx = im->texture.max_size - 1; + *dtx = (double)*tx / (im->texture.max_size); + *dtxx = (double)*txx / (im->texture.max_size); + } + else if ((x == 0) && (tw == 1)) + { + *tx = 0; + *txx = w - (x * (im->texture.max_size - 2)); + *dtx = (double)*tx / (double)edge; + *dtxx = (double)*txx / (double)edge; + } + else + { + *tx = 1; + *txx = w - (x * (im->texture.max_size - 2)); + *dtx = (double)*tx / (double)edge; + *dtxx = (double)*txx / (double)edge; + } + + if (x == 0) + *x1 = 0.0; + else + *x1 = (double)(x * (im->texture.max_size - 2)); + + if (x < (tw - 1)) + *x2 = (double)((x + 1) * (im->texture.max_size - 2)); + else + *x2 = (double)w; +} + +void __evas_gl_render_to_window(Evas_GL_Image *im, + Display *disp, Window w, int win_w, int win_h, + 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 x, y, i; + double dx, dy, dw, dh; + + if (im->state != EVAS_STATE_TEXTURE) + __evas_gl_move_state_data_to_texture(im); + glXMakeCurrent(disp, w, im->context); +/* + glClearColor(0.7, 0.7, 0.7, 1.0); + glClear(GL_COLOR_BUFFER_BIT); +*/ + glEnable(GL_BLEND); + glShadeModel(GL_FLAT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); +/* why doesnt scissor work ? */ +/* + glEnable(GL_SCISSOR_TEST); + glScissor(dst_x, win_h - dst_y - 1, dst_w, dst_h); +*/ +/* translate all poly coords in ints to normal X coord space */ + glViewport(0, 0, win_w, win_h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, win_w, 0, win_h, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glScalef(1, -1, 1); + glTranslatef(0, -win_h, 0); + /* project src and dst rects to overall dest rect */ + dw = (((double)dst_w * (double)im->w)/ (double)src_w); + dx = (double)dst_x - (((double)dst_w * (double)src_x)/ (double)src_w); + + dh = (((double)dst_h * (double)im->h)/ (double)src_h); + dy = (double)dst_y - (((double)dst_h * (double)src_y)/ (double)src_h); + for (y = 0, i = 0; y < im->texture.h; y++) + { + for (x = 0; x < im->texture.w; x++, i++) + { + int tx, ty, txx, tyy; + double x1, y1, x2, y2; + double dtx, dtxx, dty, dtyy; + + + __evas_calc_tex_and_poly(im, x, &x1, &x2, &tx, &txx, + &dtx, &dtxx, + im->texture.w, im->w, + im->texture.edge_w); + __evas_calc_tex_and_poly(im, y, &y1, &y2, &ty, &tyy, + &dty, &dtyy, + im->texture.h, im->h, + im->texture.edge_h); + x1 = dx + ((x1 * dw) / (double)im->w); + y1 = dy + ((y1 * dh) / (double)im->h); + x2 = dx + ((x2 * dw) / (double)im->w); + y2 = dy + ((y2 * dh) / (double)im->h); + glBindTexture(GL_TEXTURE_2D, im->texture.textures[i]); + glBegin(GL_POLYGON); + glTexCoord2d(dtx, dty); glVertex2d(x1, y1); + glTexCoord2d(dtxx, dty); glVertex2d(x2, y1); + glTexCoord2d(dtxx, dtyy); glVertex2d(x2, y2); + glTexCoord2d(dtx, dtyy); glVertex2d(x1, y2); + glEnd(); + } + } + glXSwapBuffers(im->buffer.display, w); + glDisable(GL_SCISSOR_TEST); +} + +Evas_GL_Image * +__evas_gl_create_image(void) +{ + Evas_GL_Image *im; + + im = malloc(sizeof(Evas_GL_Image)); + memset(im, 0, sizeof(Evas_GL_Image)); + return im; +} + +static XVisualInfo *__evas_vi = NULL; +static GLXContext __evas_gl_cx = 0; + +int +__evas_gl_capable(Display *disp) +{ + int eb, evb; + return glXQueryExtension(disp, &eb, &evb); +} + +Visual * +__evas_gl_get_visual(Display *disp) +{ + static Display *d = NULL; + + if (d != disp) + { + d = disp; + __evas_vi = glXChooseVisual(disp, DefaultScreen(disp), __evas_gl_configuration); + } + return __evas_vi->visual; +} + +Colormap +__evas_gl_get_colormap(Display *disp) +{ + static Display *d = NULL; + static Colormap cmap = 0; + + if (!__evas_vi) __evas_gl_get_visual(disp); + if (d != disp) + { + d = disp; + cmap = XCreateColormap(disp, RootWindow(disp, DefaultScreen(disp)), __evas_vi->visual, 0); + } + return cmap; +} + +void +__evas_gl_init(Display *disp) +{ + if (__evas_gl_cx) return; + + if (!__evas_gl_capable(disp)) return; + __evas_gl_get_visual(disp); + /* direct rendering client */ + __evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_TRUE); + /* GLX indirect */ +/* __evas_gl_cx = glXCreateContext(disp, __evas_vi, NULL, GL_TRUE);*/ +} + +Evas_GL_Image * +__evas_gl_image_new_from_file(Display *disp, char *file) +{ + Evas_GL_Image *im; + Imlib_Image i; + + i = imlib_load_image(file); + if (!i) return NULL; + imlib_context_set_image(i); + im = __evas_gl_create_image(); + im->w = imlib_image_get_width(); + im->h = imlib_image_get_height(); + im->data = imlib_image_get_data(); + im->texture.max_size = 256; + __evas_gl_init(disp); + im->context = __evas_gl_cx; + im->buffer.display = disp; + im->buffer.colormap = __evas_gl_get_colormap(disp); + im->buffer.visual_info = __evas_vi; + return im; +} + +void +__evas_sync(Display *disp) +{ + glXWaitGL(); + XSync(disp, False); +} + +void +__evas_flush_draw(Display *disp, Window win) +{ + glXSwapBuffers(disp, win); +} + +void +__evas_draw_rectangle(Display *disp, Window win, int x, int y, int w, int h, + int r, int g, int b, int a) +{ +}