ewooo- gl routines for evas.. been working on them...... :)

SVN revision: 2969
This commit is contained in:
Carsten Haitzler 2000-08-02 03:33:11 +00:00
parent 83dff01c43
commit b4a315b048
2 changed files with 413 additions and 1 deletions

View File

@ -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

View File

@ -0,0 +1,411 @@
/* C library header files. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xmu/StdCmap.h>
#include <X11/keysym.h>
#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)
{
}