efl/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c

418 lines
11 KiB
C
Raw Normal View History

#include "evas_gl_private.h"
static void _evas_gl_common_viewport_set(Evas_GL_Context *gc);
static void _evas_gl_common_dither_set(Evas_GL_Context *gc);
static void _evas_gl_common_blend_set(Evas_GL_Context *gc);
static void _evas_gl_common_color_set(Evas_GL_Context *gc);
static void _evas_gl_common_texture_set(Evas_GL_Context *gc);
static void _evas_gl_common_clip_set(Evas_GL_Context *gc);
static void _evas_gl_common_buf_set(Evas_GL_Context *gc);
static void _evas_gl_common_other_set(Evas_GL_Context *gc);
static Evas_GL_Context *_evas_gl_common_context = NULL;
Evas_GL_Context *
evas_gl_common_context_new(void)
{
Evas_GL_Context *gc;
if (_evas_gl_common_context)
{
_evas_gl_common_context->references++;
return _evas_gl_common_context;
}
gc = calloc(1, sizeof(Evas_GL_Context));
if (!gc) return NULL;
gc->max_texture_depth = 32;
gc->max_texture_size = 2048;
gc->read_buf = GL_BACK;
gc->write_buf = GL_BACK;
gc->dither = 1;
gc->blend = 0;
gc->references = 1;
2005-05-21 19:49:50 -07:00
gc->change.size = 1;
gc->change.dither = 1;
gc->change.blend = 1;
gc->change.color = 1;
gc->change.texture = 1;
gc->change.clip = 1;
gc->change.buf = 1;
gc->change.other = 1;
return gc;
}
void
evas_gl_common_context_free(Evas_GL_Context *gc)
{
gc->references--;
if (gc->references > 0) return;
2005-05-21 19:49:50 -07:00
if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
free(gc);
}
void
evas_gl_common_context_use(Evas_GL_Context *gc)
{
if (_evas_gl_common_context == gc) return;
if (!gc->ext.checked)
{
const GLubyte *ext;
2005-05-21 19:49:50 -07:00
ext = glGetString(GL_EXTENSIONS);
if (ext)
{
if (strstr(ext, "GL_SGIS_generate_mipmap")) gc->ext.sgis_generate_mipmap = 1;
if (strstr(ext, "GL_NV_texture_rectangle")) gc->ext.nv_texture_rectangle = 1;
if (strstr(ext, "GL_EXT_texture_rectangle")) gc->ext.nv_texture_rectangle = 1;
if (strstr(ext, "GL_ARB_texture_non_power_of_two")) gc->ext.arb_texture_non_power_of_two = 1;
printf("GL EXT supported: GL_SGIS_generate_mipmap = %x\n", gc->ext.sgis_generate_mipmap);
printf("GL EXT supported: GL_NV_texture_rectangle = %x\n", gc->ext.nv_texture_rectangle);
printf("GL EXT supported: GL_ARB_texture_non_power_of_two = %x\n", gc->ext.arb_texture_non_power_of_two);
// this causes at least nvidia's drivers to go into pathological pain when
// changing textures a lot (doing video). so we wont do anything with this
// for now, but it does work.
gc->ext.arb_texture_non_power_of_two = 0; printf("DISABLE GL_ARB_texture_non_power_of_two\n");
// gc->ext.nv_texture_rectangle = 0; printf("DISABLE GL_NV_texture_rectangle\n");
}
else
{
printf("GL EXT supported: No extensions!!!!!\n");
}
gc->ext.checked = 1;
}
_evas_gl_common_context = gc;
_evas_gl_common_viewport_set(gc);
_evas_gl_common_dither_set(gc);
_evas_gl_common_blend_set(gc);
_evas_gl_common_color_set(gc);
_evas_gl_common_texture_set(gc);
_evas_gl_common_texture_set(gc);
_evas_gl_common_clip_set(gc);
_evas_gl_common_buf_set(gc);
_evas_gl_common_other_set(gc);
}
void
evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h)
{
if ((gc->w == w) && (gc->h == h)) return;
gc->change.size = 1;
gc->w = w;
gc->h = h;
if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
}
void
evas_gl_common_context_color_set(Evas_GL_Context *gc, int r, int g, int b, int a)
{
if (r < 0) r = 0;
else if (r > 255) r = 255;
if (g < 0) g = 0;
else if (g > 255) g = 255;
if (b < 0) b = 0;
else if (b > 255) b = 255;
if (a < 0) a = 0;
else if (a > 255) a = 255;
if ((gc->r == r) && (gc->g == g) && (gc->b == b) && (gc->a == a)) return;
gc->change.color = 1;
gc->r = r;
gc->g = g;
gc->b = b;
gc->a = a;
if (_evas_gl_common_context == gc) _evas_gl_common_color_set(gc);
}
void
evas_gl_common_context_blend_set(Evas_GL_Context *gc, int blend)
{
if (((blend) && (gc->blend)) || ((!blend) && (!gc->blend))) return;
gc->change.blend = 1;
gc->blend = blend;
if (_evas_gl_common_context == gc) _evas_gl_common_blend_set(gc);
}
void
evas_gl_common_context_dither_set(Evas_GL_Context *gc, int dither)
{
if (((dither) && (gc->dither)) || ((!dither) && (!gc->dither))) return;
gc->change.dither = 1;
gc->dither = dither;
if (_evas_gl_common_context == gc) _evas_gl_common_dither_set(gc);
}
void
evas_gl_common_context_texture_set(Evas_GL_Context *gc, Evas_GL_Texture *tex, int smooth, int w, int h)
{
if (gc->font_texture > 0)
{
gc->font_texture = 0;
gc->change.texture = 1;
}
if (gc->texture != tex)
{
if (gc->texture) gc->texture->references--;
gc->texture = tex;
gc->change.texture = 1;
if (tex) tex->references++;
}
if (tex)
{
2005-05-21 19:49:50 -07:00
if (((smooth) && (!tex->smooth)) ||
((!smooth) && (tex->smooth)))
{
tex->smooth = smooth;
tex->changed = 1;
}
tex->uw = w;
tex->uh = h;
}
if (_evas_gl_common_context == gc) _evas_gl_common_texture_set(gc);
}
void
evas_gl_common_context_font_texture_set(Evas_GL_Context *gc, Evas_GL_Font_Texture *ft)
{
if (gc->texture)
{
if (gc->texture) gc->texture->references--;
gc->texture = NULL;
gc->change.texture = 1;
}
if (gc->font_texture != ft->texture)
{
gc->font_texture = ft->texture;
gc->font_texture_rectangle = ft->pool->rectangle;
gc->change.texture = 1;
}
if (!gc->change.texture) return;
if (_evas_gl_common_context == gc) _evas_gl_common_texture_set(gc);
}
void
evas_gl_common_context_clip_set(Evas_GL_Context *gc, int on, int x, int y, int w, int h)
{
if (x < 0)
{
2005-05-21 19:49:50 -07:00
w += x;
x = 0;
}
if (y < 0)
{
2005-05-21 19:49:50 -07:00
h += y;
y = 0;
}
if (w < 0) w = 0;
if (h < 0) h = 0;
if (((!on) && (!gc->clip.active)) ||
2005-05-21 19:49:50 -07:00
((on) && (gc->clip.active) &&
(x == gc->clip.x) && (y == gc->clip.y) &&
(w == gc->clip.w) && (h == gc->clip.h)))
return;
gc->change.clip = 1;
gc->clip.active = on;
gc->clip.x = x;
gc->clip.y = y;
gc->clip.w = w;
gc->clip.h = h;
if (_evas_gl_common_context == gc) _evas_gl_common_clip_set(gc);
}
void
evas_gl_common_context_read_buf_set(Evas_GL_Context *gc, GLenum buf)
{
if (gc->read_buf == buf) return;
gc->change.buf = 1;
gc->read_buf = buf;
if (_evas_gl_common_context == gc) _evas_gl_common_buf_set(gc);
}
void
evas_gl_common_context_write_buf_set(Evas_GL_Context *gc, GLenum buf)
{
if (gc->write_buf == buf) return;
gc->change.buf = 1;
gc->write_buf = buf;
if (_evas_gl_common_context == gc) _evas_gl_common_buf_set(gc);
}
static void
_evas_gl_common_viewport_set(Evas_GL_Context *gc)
{
if (!gc->change.size) return;
glViewport(0, 0, gc->w, gc->h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, gc->w, 0, gc->h, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(1, -1, 1);
2005-05-21 19:49:50 -07:00
glTranslatef(0, - gc->h, 0);
gc->change.size = 0;
}
static void
_evas_gl_common_dither_set(Evas_GL_Context *gc)
{
if (!gc->change.dither) return;
if (gc->dither)
glEnable(GL_DITHER);
else
glDisable(GL_DITHER);
gc->change.dither = 0;
}
static void
_evas_gl_common_blend_set(Evas_GL_Context *gc)
{
if (!gc->change.blend) return;
2005-05-21 19:49:50 -07:00
if (gc->blend)
{
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else
glDisable(GL_BLEND);
gc->change.blend = 0;
}
static void
_evas_gl_common_color_set(Evas_GL_Context *gc)
{
if (!gc->change.color) return;
glColor4d((double)gc->r / 255.0,
(double)gc->g / 255.0,
(double)gc->b / 255.0,
(double)gc->a / 255.0);
gc->change.color = 0;
}
static void
_evas_gl_common_texture_set(Evas_GL_Context *gc)
{
if (!gc->change.texture) return;
if (gc->font_texture > 0)
{
if (gc->font_texture_rectangle)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_NV);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, gc->font_texture);
}
else
{
if (gc->ext.nv_texture_rectangle)
glDisable(GL_TEXTURE_RECTANGLE_NV);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gc->font_texture);
}
}
else if (gc->texture)
{
if (gc->texture->rectangle)
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_NV);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, gc->texture->texture);
}
else
{
if (gc->ext.nv_texture_rectangle) glDisable(GL_TEXTURE_RECTANGLE_NV);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gc->texture->texture);
}
if (gc->texture->rectangle)
{
if (gc->texture->changed)
{
gc->texture->changed = 0;
}
}
else
{
if (gc->texture->changed)
{
if (gc->texture->rectangle)
{
if (gc->texture->smooth)
{
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
}
else
{
if (gc->texture->smooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (gc->texture->have_mipmaps)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
}
gc->texture->changed = 0;
}
}
}
else if (gc->font_texture == 0)
{
glDisable(GL_TEXTURE_2D);
if (gc->ext.nv_texture_rectangle) glDisable(GL_TEXTURE_RECTANGLE_NV);
}
gc->change.texture = 0;
}
static void
_evas_gl_common_clip_set(Evas_GL_Context *gc)
{
if (!gc->change.clip) return;
2003-09-10 19:30:34 -07:00
/* might be faster using clip planes ??? glClipPlane() */
if (gc->clip.active)
{
glEnable(GL_SCISSOR_TEST);
glScissor(gc->clip.x,
2005-05-21 19:49:50 -07:00
gc->h - gc->clip.y - gc->clip.h,
gc->clip.w,
gc->clip.h);
}
else
glDisable(GL_SCISSOR_TEST);
gc->change.clip = 0;
}
static void
_evas_gl_common_buf_set(Evas_GL_Context *gc)
{
if (!gc->change.buf) return;
glDrawBuffer(gc->write_buf);
glReadBuffer(gc->read_buf);
gc->change.buf = 0;
}
static void
_evas_gl_common_other_set(Evas_GL_Context *gc)
{
if (!gc->change.other) return;
glShadeModel(GL_FLAT);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
gc->change.other = 0;
}