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

3329 lines
117 KiB
C

#include "evas_gl_private.h"
#ifdef HAVE_DLSYM
# include <dlfcn.h> /* dlopen,dlclose,etc */
#else
# error gl_common should not get compiled if dlsym is not found on the system!
#endif
#define PRG_INVALID 0xffffffff
#define GLPIPES 1
static int sym_done = 0;
int _evas_engine_GL_common_log_dom = -1;
typedef void (*glsym_func_void) ();
typedef void *(*glsym_func_void_ptr) ();
typedef GLboolean (*glsym_func_boolean) ();
typedef const char *(*glsym_func_const_char_ptr) ();
void (*glsym_glGenFramebuffers) (GLsizei a, GLuint *b) = NULL;
void (*glsym_glBindFramebuffer) (GLenum a, GLuint b) = NULL;
void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL;
void (*glsym_glDeleteFramebuffers) (GLsizei a, const GLuint *b) = NULL;
void (*glsym_glGetProgramBinary) (GLuint a, GLsizei b, GLsizei *c, GLenum *d, void *e) = NULL;
void (*glsym_glProgramBinary) (GLuint a, GLenum b, const void *c, GLint d) = NULL;
void (*glsym_glProgramParameteri) (GLuint a, GLuint b, GLint d) = NULL;
void (*glsym_glReleaseShaderCompiler)(void) = NULL;
void *(*glsym_glMapBuffer) (GLenum a, GLenum b) = NULL;
GLboolean (*glsym_glUnmapBuffer) (GLenum a) = NULL;
void (*glsym_glStartTiling) (GLuint a, GLuint b, GLuint c, GLuint d, GLuint e) = NULL;
void (*glsym_glEndTiling) (GLuint a) = NULL;
void (*glsym_glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data) = NULL;
#ifdef GL_GLES
// just used for finding symbols :)
typedef void (*_eng_fn) (void);
typedef _eng_fn (*glsym_func_eng_fn) ();
typedef unsigned int (*secsym_func_uint) ();
typedef void *(*secsym_func_void_ptr) ();
static _eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL;
void *(*secsym_eglCreateImage) (void *a, void *b, GLenum c, void *d, const int *e) = NULL;
unsigned int (*secsym_eglDestroyImage) (void *a, void *b) = NULL;
void (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL;
void *(*secsym_eglMapImageSEC) (void *a, void *b, int c, int d) = NULL;
unsigned int (*secsym_eglUnmapImageSEC) (void *a, void *b, int c) = NULL;
unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b, int c, int *d) = NULL;
#else
typedef void (*_eng_fn) (void);
typedef _eng_fn (*glsym_func_eng_fn) ();
static _eng_fn (*glsym_glXGetProcAddress) (const char *a) = NULL;
#endif
static int dbgflushnum = -1;
static void
sym_missing(void)
{
ERR("GL symbols missing!");
}
static void
gl_symbols(void)
{
if (sym_done) return;
sym_done = 1;
/* FIXME: If using the SDL engine, we should use SDL_GL_GetProcAddress
* instead of dlsym
* if (!dst) dst = (typ)SDL_GL_GetProcAddress(sym)
*/
#ifdef GL_GLES
#define FINDSYM(dst, sym, typ) \
if (glsym_eglGetProcAddress) { \
if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \
} else { \
if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \
}
FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn);
FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn);
FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn);
FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn);
#else
#define FINDSYM(dst, sym, typ) \
if (glsym_glXGetProcAddress) { \
if (!dst) dst = (typ)glsym_glXGetProcAddress(sym); \
} else { \
if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \
}
FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddressEXT", glsym_func_eng_fn);
FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddressARB", glsym_func_eng_fn);
FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddress", glsym_func_eng_fn);
#endif
#define FINDSYM2(dst, sym, typ) if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
#define FALLBAK(dst, typ) if (!dst) dst = (typ)sym_missing
#ifdef GL_GLES
FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
FINDSYM2(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
#else
FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersEXT", glsym_func_void);
FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffersARB", glsym_func_void);
FINDSYM(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
// nvidia tegra3 drivers seem to not expose via getprocaddress, but dlsym finds it
FINDSYM2(glsym_glGenFramebuffers, "glGenFramebuffers", glsym_func_void);
FALLBAK(glsym_glGenFramebuffers, glsym_func_void);
#endif
#ifdef GL_GLES
FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
FINDSYM2(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
#else
FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferEXT", glsym_func_void);
FINDSYM(glsym_glBindFramebuffer, "glBindFramebufferARB", glsym_func_void);
FINDSYM(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
// nvidia tegra3 drivers seem to not expose via getprocaddress, but dlsym finds it
FINDSYM2(glsym_glBindFramebuffer, "glBindFramebuffer", glsym_func_void);
FALLBAK(glsym_glBindFramebuffer, glsym_func_void);
#endif
FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DEXT", glsym_func_void);
FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2DARB", glsym_func_void);
FINDSYM(glsym_glFramebufferTexture2D, "glFramebufferTexture2D", glsym_func_void);
// nvidia tegra3 drivers seem to not expose via getprocaddress, but dlsym finds it
FINDSYM2(glsym_glFramebufferTexture2D, "glFramebufferTexture2D", glsym_func_void);
FALLBAK(glsym_glFramebufferTexture2D, glsym_func_void);
FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersEXT", glsym_func_void);
FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB", glsym_func_void);
FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffers", glsym_func_void);
// nvidia tegra3 drivers seem to not expose via getprocaddress, but dlsym finds it
FINDSYM2(glsym_glDeleteFramebuffers, "glDeleteFramebuffers", glsym_func_void);
FALLBAK(glsym_glDeleteFramebuffers, glsym_func_void);
FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", glsym_func_void);
FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryKHR", glsym_func_void);
FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", glsym_func_void);
FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryARB", glsym_func_void);
FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", glsym_func_void);
FINDSYM(glsym_glProgramBinary, "glProgramBinaryOES", glsym_func_void);
FINDSYM(glsym_glProgramBinary, "glProgramBinaryKHR", glsym_func_void);
FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", glsym_func_void);
FINDSYM(glsym_glProgramBinary, "glProgramBinaryARB", glsym_func_void);
FINDSYM(glsym_glProgramBinary, "glProgramBinary", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void);
FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompilerEXT", glsym_func_void);
FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompilerARB", glsym_func_void);
FINDSYM(glsym_glReleaseShaderCompiler, "glReleaseShaderCompiler", glsym_func_void);
FINDSYM(glsym_glStartTiling, "glStartTilingQCOM", glsym_func_void);
FINDSYM(glsym_glStartTiling, "glStartTiling", glsym_func_void);
FINDSYM(glsym_glStartTiling, "glActivateTileQCOM", glsym_func_void);
FINDSYM(glsym_glEndTiling, "glEndTilingQCOM", glsym_func_void);
FINDSYM(glsym_glEndTiling, "glEndTiling", glsym_func_void);
if (!getenv("EVAS_GL_MAPBUFFER_DISABLE"))
{
FINDSYM(glsym_glMapBuffer, "glMapBufferOES", glsym_func_void_ptr);
FINDSYM(glsym_glMapBuffer, "glMapBufferEXT", glsym_func_void_ptr);
FINDSYM(glsym_glMapBuffer, "glMapBufferARB", glsym_func_void_ptr);
FINDSYM(glsym_glMapBuffer, "glMapBufferKHR", glsym_func_void_ptr);
FINDSYM(glsym_glMapBuffer, "glMapBuffer", glsym_func_void_ptr);
FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferOES", glsym_func_boolean);
FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferEXT", glsym_func_boolean);
FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferARB", glsym_func_boolean);
FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferKHR", glsym_func_boolean);
FINDSYM(glsym_glUnmapBuffer, "glUnmapBuffer", glsym_func_boolean);
}
#ifdef GL_GLES
// yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing
// but it will work as the egl/glx layer calls gl core common stuff and thus
// these symbols will work. making the glx/egl + x11 layer do this kind-of is
// wrong as this is not x11 (output) layer specific like the native surface
// stuff. this is generic zero-copy textures for gl
FINDSYM(secsym_eglCreateImage, "eglCreateImageOES", secsym_func_void_ptr);
FINDSYM(secsym_eglCreateImage, "eglCreateImageKHR", secsym_func_void_ptr);
FINDSYM(secsym_eglCreateImage, "eglCreateImageEXT", secsym_func_void_ptr);
FINDSYM(secsym_eglCreateImage, "eglCreateImageARB", secsym_func_void_ptr);
FINDSYM(secsym_eglCreateImage, "eglCreateImage", secsym_func_void_ptr);
FINDSYM(secsym_eglDestroyImage, "eglDestroyImageOES", secsym_func_uint);
FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR", secsym_func_uint);
FINDSYM(secsym_eglDestroyImage, "eglDestroyImageEXT", secsym_func_uint);
FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB", secsym_func_uint);
FINDSYM(secsym_eglDestroyImage, "eglDestroyImage", secsym_func_uint);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriOES", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriKHR", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void);
FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void);
FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", glsym_func_void);
FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC", secsym_func_void_ptr);
FINDSYM(secsym_eglUnmapImageSEC, "eglUnmapImageSEC", secsym_func_uint);
FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint);
#endif
FINDSYM(glsym_glReadPixels, "glReadPixels", glsym_func_void);
}
static void shader_array_flush(Evas_Engine_GL_Context *gc);
static Evas_Engine_GL_Context *_evas_gl_common_context = NULL;
static Evas_GL_Shared *shared = NULL;
void
glerr(int err, const char *file, const char *func, int line, const char *op)
{
const char *errmsg;
char buf[32];
switch (err)
{
case GL_INVALID_ENUM:
errmsg = "GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
errmsg = "GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
errmsg = "GL_INVALID_OPERATION";
break;
case GL_OUT_OF_MEMORY:
errmsg = "GL_OUT_OF_MEMORY";
break;
default:
snprintf(buf, sizeof(buf), "%#x", err);
errmsg = buf;
}
eina_log_print(_evas_engine_GL_common_log_dom, EINA_LOG_LEVEL_ERR,
file, func, line, "%s: %s", op, errmsg);
}
static void
matrix_ortho(GLfloat *m,
GLfloat l, GLfloat r,
GLfloat t, GLfloat b,
GLfloat near, GLfloat far,
int rot, int vw, int vh,
int foc, GLfloat orth)
{
GLfloat rotf;
GLfloat cosv, sinv;
GLfloat tx, ty;
rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
tx = -0.5 * (1.0 - orth);
ty = -0.5 * (1.0 - orth);
if (rot == 90)
{
tx += -(vw * 1.0);
ty += -(vh * 0.0);
}
if (rot == 180)
{
tx += -(vw * 1.0);
ty += -(vh * 1.0);
}
if (rot == 270)
{
tx += -(vw * 0.0);
ty += -(vh * 1.0);
}
cosv = cos(rotf);
sinv = sin(rotf);
m[0] = (2.0 / (r - l)) * ( cosv);
m[1] = (2.0 / (r - l)) * ( sinv);
m[2] = 0.0;
m[3] = 0.0;
m[4] = (2.0 / (t - b)) * (-sinv);
m[5] = (2.0 / (t - b)) * ( cosv);
m[6] = 0.0;
m[7] = 0.0;
m[8] = 0.0;
m[9] = 0.0;
m[10] = -(2.0 / (far - near));
m[11] = 1.0 / (GLfloat)foc;
m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
m[14] = (m[2] * tx) + (m[6] * ty) - ((near + far) / (far - near));
m[15] = (m[3] * tx) + (m[7] * ty) + orth;
}
static int
_evas_gl_common_version_check()
{
char *version;
char *tmp;
char *tmp2;
int major;
int minor;
/*
* glGetString returns a string describing the current GL connection.
* GL_VERSION is used to get the version of the connection
*/
version = (char *)glGetString(GL_VERSION);
/*
* OpengL ES
*
* 1.* : The form is:
*
* OpenGL ES-<profile> <major>.<minor>
*
* where <profile> is either "CM" or "CL". The minor can be followed by the vendor
* specific information
*
* 2.0 : The form is:
*
* OpenGL<space>ES<space><version number><space><vendor-specific information>
*/
/* OpenGL ES 1.* ? */
if ((tmp = strstr(version, "OpenGL ES-CM ")) || (tmp = strstr(version, "OpenGL ES-CL ")))
{
/* Not supported */
return 0;
}
/* OpenGL ES 2.* ? */
if ((tmp = strstr(version, "OpenGL ES ")))
{
/* Supported */
return 1;
}
/*
* OpenGL
*
* The GL_VERSION and GL_SHADING_LANGUAGE_VERSION strings begin with a
* version number. The version number uses one of these forms:
*
* major_number.minor_number
* major_number.minor_number.release_number
*
* Vendor-specific information may follow the version number. Its format
* depends on the implementation, but a space always separates the
* version number and the vendor-specific information.
*/
/* glGetString() returns a static string, and we are going to */
/* modify it, so we get a copy first */
version = strdup(version);
if (!version)
return 0;
tmp = strchr(version, '.');
/* the first '.' always exists */
*tmp = '\0';
major = atoi(version);
/* FIXME: maybe we can assume that minor in only a cipher */
tmp2 = ++tmp;
while ((*tmp != '.') && (*tmp != ' ') && (*tmp != '\0'))
tmp++;
/* *tmp is '\0' : version is major_number.minor_number */
/* *tmp is '.' : version is major_number.minor_number.release_number */
/* *tmp is ' ' : version is major_number.minor_number followed by vendor */
*tmp = '\0';
minor = atoi(tmp2);
free(version);
if (((major == 1) && (minor >= 4)) || (major >= 2))
return 1;
return 0;
}
static void
_evas_gl_common_viewport_set(Evas_Engine_GL_Context *gc)
{
GLfloat proj[16];
unsigned int i;
int w = 1, h = 1, m = 1, rot = 1, foc = 0;
EINA_SAFETY_ON_NULL_RETURN(gc);
foc = gc->foc;
// surface in pipe 0 will be the same as all pipes
if ((gc->pipe[0].shader.surface == gc->def_surface) ||
(!gc->pipe[0].shader.surface))
{
w = gc->w;
h = gc->h;
rot = gc->rot;
}
else
{
w = gc->pipe[0].shader.surface->w;
h = gc->pipe[0].shader.surface->h;
rot = 0;
m = -1;
}
#ifdef GL_GLES
if (gc->shared->eglctxt == gc->eglctxt)
#endif
{
if ((!gc->change.size) ||
(
(gc->shared->w == w) && (gc->shared->h == h) &&
(gc->shared->rot == rot) && (gc->shared->foc == gc->foc) &&
(gc->shared->mflip == m)
)
)
return;
}
#ifdef GL_GLES
gc->shared->eglctxt = gc->eglctxt;
#endif
gc->shared->w = w;
gc->shared->h = h;
gc->shared->rot = rot;
gc->shared->mflip = m;
gc->shared->foc = foc;
gc->shared->z0 = gc->z0;
gc->shared->px = gc->px;
gc->shared->py = gc->py;
gc->change.size = 0;
if (foc == 0)
{
if ((rot == 0) || (rot == 180))
glViewport(0, 0, w, h);
else
glViewport(0, 0, h, w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// std matrix
if (m == 1)
matrix_ortho(proj,
0, w, 0, h,
-1000000.0, 1000000.0,
rot, w, h,
1, 1.0);
// v flipped matrix for render-to-texture
else
matrix_ortho(proj,
0, w, h, 0,
-1000000.0, 1000000.0,
rot, w, h,
1, 1.0);
}
else
{
int px, py, vx, vy, vw = 0, vh = 0, ax = 0, ay = 0, ppx = 0, ppy = 0;
px = gc->shared->px;
py = gc->shared->py;
if ((rot == 0 ) || (rot == 90 )) ppx = px;
else if ((rot == 180) || (rot == 270)) ppx = w - px;
if ((rot == 0 ) || (rot == 270)) ppy = py;
else if ((rot == 90 ) || (rot == 180)) ppy = h - py;
vx = ((w / 2) - ppx);
if (vx >= 0)
{
vw = w + (2 * vx);
if ((rot == 0 ) || (rot == 90 )) ax = 2 * vx;
else if ((rot == 180) || (rot == 270)) ax = 0;
}
else
{
vw = w - (2 * vx);
if ((rot == 0 ) || (rot == 90 )) ax = 0;
else if ((rot == 180) || (rot == 270)) ax = ppx - px;
vx = 0;
}
vy = ((h / 2) - ppy);
if (vy < 0)
{
vh = h - (2 * vy);
if (rot == 0) ay = 0;
else if ((rot == 90 ) || (rot == 180) || (rot == 270)) ay = ppy - py;
vy = -vy;
}
else
{
vh = h + (2 * vy);
if ((rot == 0 ) || (rot == 270)) ay = 2 * vy;
else if ((rot == 90 ) || (rot == 180)) ay = 0;
vy = 0;
}
if (m == -1) ay = vy * 2;
if ((rot == 0) || (rot == 180))
glViewport(-2 * vx, -2 * vy, vw, vh);
else
glViewport(-2 * vy, -2 * vx, vh, vw);
if (m == 1)
matrix_ortho(proj, 0, vw, 0, vh,
-1000000.0, 1000000.0,
rot, vw, vh,
foc, 0.0);
else
matrix_ortho(proj, 0, vw, vh, 0,
-1000000.0, 1000000.0,
rot, vw, vh,
foc, 0.0);
gc->shared->ax = ax;
gc->shared->ay = ay;
}
for (i = 0; i < SHADER_LAST; ++i)
{
glUseProgram(gc->shared->shader[i].prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glUniformMatrix4fv(glGetUniformLocation(gc->shared->shader[i].prog, "mvp"), 1, GL_FALSE, proj);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(gc->shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
Evas_Engine_GL_Context *
evas_gl_common_context_new(void)
{
Evas_Engine_GL_Context *gc;
const char *s;
int i;
#if 1
if (_evas_gl_common_context)
{
_evas_gl_common_context->references++;
return _evas_gl_common_context;
}
#endif
if (!_evas_gl_common_version_check())
return NULL;
gc = calloc(1, sizeof(Evas_Engine_GL_Context));
if (!gc) return NULL;
gl_symbols();
gc->references = 1;
_evas_gl_common_context = gc;
for (i = 0; i < MAX_PIPES; i++)
{
gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
if (glsym_glMapBuffer && glsym_glUnmapBuffer)
{
glGenBuffers(1, &gc->pipe[i].array.buffer);
gc->pipe[i].array.buffer_alloc = 0;
gc->pipe[i].array.buffer_use = 0;
}
}
if (!shared)
{
const GLubyte *ext;
shared = calloc(1, sizeof(Evas_GL_Shared));
ext = glGetString(GL_EXTENSIONS);
if (ext)
{
if (getenv("EVAS_GL_INFO"))
fprintf(stderr, "EXT:\n%s\n", ext);
if ((strstr((char *)ext, "GL_ARB_texture_non_power_of_two")) ||
(strstr((char *)ext, "OES_texture_npot")) ||
(strstr((char *)ext, "GL_IMG_texture_npot")))
shared->info.tex_npo2 = 1;
if ((strstr((char *)ext, "GL_NV_texture_rectangle")) ||
(strstr((char *)ext, "GL_EXT_texture_rectangle")) ||
(strstr((char *)ext, "GL_ARB_texture_rectangle")))
shared->info.tex_rect = 1;
if ((strstr((char *)ext, "GL_ARB_get_program_binary")) ||
(strstr((char *)ext, "GL_OES_get_program_binary")))
shared->info.bin_program = 1;
else
glsym_glGetProgramBinary = NULL;
#ifdef GL_UNPACK_ROW_LENGTH
shared->info.unpack_row_length = 1;
# ifdef GL_GLES
if (!strstr((char *)ext, "_unpack_subimage"))
shared->info.unpack_row_length = 0;
# endif
#endif
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
if ((strstr((char *)ext, "GL_EXT_texture_filter_anisotropic")))
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,
&(shared->info.anisotropic));
#endif
#ifdef GL_BGRA
if ((strstr((char *)ext, "GL_EXT_bgra")) ||
(strstr((char *)ext, "GL_EXT_texture_format_BGRA8888")))
shared->info.bgra = 1;
#endif
#ifdef GL_GLES
// FIXME: there should be an extension name/string to check for
// not just symbols in the lib
i = 0;
s = getenv("EVAS_GL_NO_MAP_IMAGE_SEC");
if (s) i = atoi(s);
if (!i)
{
// test for all needed symbols - be "conservative" and
// need all of it
if ((secsym_eglCreateImage) &&
(secsym_eglDestroyImage) &&
(secsym_glEGLImageTargetTexture2DOES) &&
(secsym_eglMapImageSEC) &&
(secsym_eglUnmapImageSEC) &&
(secsym_eglGetImageAttribSEC))
shared->info.sec_image_map = 1;
}
#endif
if (!strstr((char *)ext, "GL_QCOM_tiled_rendering"))
{
glsym_glStartTiling = NULL;
glsym_glEndTiling = NULL;
}
}
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
&(shared->info.max_texture_units));
glGetIntegerv(GL_MAX_TEXTURE_SIZE,
&(shared->info.max_texture_size));
shared->info.max_vertex_elements = 6 * 100000;
#ifdef GL_MAX_ELEMENTS_VERTICES
/* only applies to glDrawRangeElements. don't really need to get it.
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES,
&(shared->info.max_vertex_elements));
*/
#endif
s = getenv("EVAS_GL_VERTEX_MAX");
if (s) shared->info.max_vertex_elements = atoi(s);
if (shared->info.max_vertex_elements < 6)
shared->info.max_vertex_elements = 6;
// magic numbers that are a result of imperical testing and getting
// "best case" performance across a range of systems
shared->info.tune.cutout.max = DEF_CUTOUT;
shared->info.tune.pipes.max = DEF_PIPES;
shared->info.tune.atlas.max_alloc_size = DEF_ATLAS_ALLOC;
shared->info.tune.atlas.max_alloc_alpha_size = DEF_ATLAS_ALLOC_ALPHA;
shared->info.tune.atlas.max_w = DEF_ATLAS_W;
shared->info.tune.atlas.max_h = DEF_ATLAS_H;
shared->info.tune.atlas.slot_size = DEF_ATLAS_SLOT;
// per gpu hacks. based on impirical measurement of some known gpu's
s = (const char *)glGetString(GL_RENDERER);
if (s)
{
if (strstr(s, "PowerVR SGX 540"))
shared->info.tune.pipes.max = DEF_PIPES_SGX_540;
else if (strstr(s, "NVIDIA Tegra 3"))
shared->info.tune.pipes.max = DEF_PIPES_TEGRA_3;
else if (strstr(s, "NVIDIA Tegra"))
shared->info.tune.pipes.max = DEF_PIPES_TEGRA_2;
}
if (!getenv("EVAS_GL_MAPBUFFER"))
{
glsym_glMapBuffer = NULL;
glsym_glUnmapBuffer= NULL;
}
#define GETENVOPT(name, tune_param, min, max) \
do { \
const char *__v = getenv(name); \
if (__v) { \
shared->info.tune.tune_param = atoi(__v); \
if (shared->info.tune.tune_param > max) \
shared->info.tune.tune_param = max; \
else if (shared->info.tune.tune_param < min) \
shared->info.tune.tune_param = min; \
} \
} while (0)
GETENVOPT("EVAS_GL_CUTOUT_MAX", cutout.max, -1, 0x7fffffff);
GETENVOPT("EVAS_GL_PIPES_MAX", pipes.max, 1, MAX_PIPES);
GETENVOPT("EVAS_GL_ATLAS_ALLOC_SIZE", atlas.max_alloc_size, MIN_ATLAS_ALLOC, MAX_ATLAS_ALLOC);
GETENVOPT("EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE", atlas.max_alloc_alpha_size, MIN_ATLAS_ALLOC_ALPHA, MAX_ATLAS_ALLOC_ALPHA);
GETENVOPT("EVAS_GL_ATLAS_MAX_W", atlas.max_w, 0, MAX_ATLAS_W);
GETENVOPT("EVAS_GL_ATLAS_MAX_H", atlas.max_h, 0, MAX_ATLAS_H);
GETENVOPT("EVAS_GL_ATLAS_SLOT_SIZE", atlas.slot_size, MIN_ATLAS_SLOT, MAX_ATLAS_SLOT);
s = (const char *)getenv("EVAS_GL_GET_PROGRAM_BINARY");
if (s)
{
if (atoi(s) == 0) shared->info.bin_program = 0;
}
if (getenv("EVAS_GL_INFO"))
fprintf(stderr,
"max tex size %ix%i\n"
"max units %i\n"
"non-power-2 tex %i\n"
"rect tex %i\n"
"bgra : %i\n"
"max ansiotropic filtering: %3.3f\n"
"egl sec map image: %i\n"
"max vertex count: %i\n"
"\n"
"(can set EVAS_GL_VERTEX_MAX EVAS_GL_NO_MAP_IMAGE_SEC EVAS_GL_INFO EVAS_GL_MEMINFO )\n"
"\n"
"EVAS_GL_GET_PROGRAM_BINARY: %i\n"
"EVAS_GL_CUTOUT_MAX: %i\n"
"EVAS_GL_PIPES_MAX: %i\n"
"EVAS_GL_ATLAS_ALLOC_SIZE: %i\n"
"EVAS_GL_ATLAS_ALLOC_ALPHA_SIZE: %i\n"
"EVAS_GL_ATLAS_MAX_W x EVAS_GL_ATLAS_MAX_H: %i x %i\n"
"EVAS_GL_ATLAS_SLOT_SIZE: %i\n"
,
(int)shared->info.max_texture_size, (int)shared->info.max_texture_size,
(int)shared->info.max_texture_units,
(int)shared->info.tex_npo2,
(int)shared->info.tex_rect,
(int)shared->info.bgra,
(double)shared->info.anisotropic,
(int)shared->info.sec_image_map,
(int)shared->info.max_vertex_elements,
(int)shared->info.bin_program,
(int)shared->info.tune.cutout.max,
(int)shared->info.tune.pipes.max,
(int)shared->info.tune.atlas.max_alloc_size,
(int)shared->info.tune.atlas.max_alloc_alpha_size,
(int)shared->info.tune.atlas.max_w, (int)shared->info.tune.atlas.max_h,
(int)shared->info.tune.atlas.slot_size
);
glDisable(GL_DEPTH_TEST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glEnable(GL_DITHER);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisable(GL_BLEND);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// no dest alpha
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
// glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
glDepthMask(GL_FALSE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
if (shared->info.anisotropic > 0.0)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
#endif
glEnableVertexAttribArray(SHAD_VERTEX);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glEnableVertexAttribArray(SHAD_COLOR);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (!evas_gl_common_shader_program_init(shared)) goto error;
#define SHADER_TEXTURE_ADD(Shared, Shader, Name) \
glUseProgram(Shared->shader[SHADER_##Shader].prog); \
GLERR(__FUNCTION__, __FILE__, __LINE__, ""); \
glUniform1i(glGetUniformLocation(Shared->shader[SHADER_##Shader].prog, #Name), Shared->shader[SHADER_##Shader].tex_count++); \
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
SHADER_TEXTURE_ADD(shared, YUV, tex);
SHADER_TEXTURE_ADD(shared, YUV, texu);
SHADER_TEXTURE_ADD(shared, YUV, texv);
SHADER_TEXTURE_ADD(shared, YUY2, tex);
SHADER_TEXTURE_ADD(shared, YUY2, texuv);
SHADER_TEXTURE_ADD(shared, NV12, tex);
SHADER_TEXTURE_ADD(shared, NV12, texuv);
SHADER_TEXTURE_ADD(shared, YUV_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texu);
SHADER_TEXTURE_ADD(shared, YUV_NOMUL, texv);
SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, YUY2_NOMUL, texuv);
SHADER_TEXTURE_ADD(shared, NV12_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, NV12_NOMUL, texuv);
SHADER_TEXTURE_ADD(shared, IMG_MASK, tex);
SHADER_TEXTURE_ADD(shared, IMG_MASK, texm);
if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
evas_gl_common_shader_program_init_done();
// in shader:
// uniform sampler2D tex[8];
//
// in code:
// GLuint texes[8];
// GLint loc = glGetUniformLocation(prog, "tex");
// glUniform1iv(loc, 8, texes);
shared->native_pm_hash = eina_hash_int32_new(NULL);
shared->native_tex_hash = eina_hash_int32_new(NULL);
}
gc->shared = shared;
gc->shared->references++;
_evas_gl_common_viewport_set(gc);
gc->def_surface = evas_gl_common_image_surface_new(gc, 1, 1, 1);
return gc;
error:
evas_gl_common_context_free(gc);
return NULL;
}
void
evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
{
int i, j;
Eina_List *l;
gc->references--;
if (gc->references > 0) return;
if (gc->shared) gc->shared->references--;
if (gc->def_surface) evas_gl_common_image_free(gc->def_surface);
if (glsym_glMapBuffer && glsym_glUnmapBuffer)
{
for (i = 0; i < MAX_PIPES; i++)
glDeleteBuffers(1, &gc->pipe[i].array.buffer);
}
if (gc->shared)
{
for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
{
if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm);
if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
if (gc->pipe[i].array.texsam) free(gc->pipe[i].array.texsam);
}
}
while (gc->font_glyph_textures)
evas_gl_common_texture_free(gc->font_glyph_textures->data, EINA_TRUE);
if ((gc->shared) && (gc->shared->references == 0))
{
Evas_GL_Texture_Pool *pt;
for (i = 0; i < SHADER_LAST; ++i)
evas_gl_common_shader_program_shutdown(&(gc->shared->shader[i]));
while (gc->shared->images)
{
evas_gl_common_image_free(gc->shared->images->data);
}
for (i = 0; i < 33; i++)
{
for (j = 0; j < 3; j++)
{
EINA_LIST_FOREACH(gc->shared->tex.atlas[i][j], l, pt)
evas_gl_texture_pool_empty(pt);
eina_list_free(gc->shared->tex.atlas[i][j]);
}
}
EINA_LIST_FOREACH(gc->shared->tex.whole, l, pt)
evas_gl_texture_pool_empty(pt);
eina_list_free(gc->shared->tex.whole);
eina_hash_free(gc->shared->native_pm_hash);
eina_hash_free(gc->shared->native_tex_hash);
free(gc->shared);
shared = NULL;
}
if (gc == _evas_gl_common_context) _evas_gl_common_context = NULL;
free(gc);
}
void
evas_gl_common_context_use(Evas_Engine_GL_Context *gc)
{
if (_evas_gl_common_context == gc) return;
_evas_gl_common_context = gc;
if (gc) _evas_gl_common_viewport_set(gc);
}
void
evas_gl_common_context_newframe(Evas_Engine_GL_Context *gc)
{
int i;
if (dbgflushnum < 0)
{
dbgflushnum = 0;
if (getenv("EVAS_GL_DBG")) dbgflushnum = 1;
}
if (dbgflushnum) printf("----prev-flushnum: %i -----------------------------------\n", gc->flushnum);
// fprintf(stderr, "------------------------\n");
gc->flushnum = 0;
gc->state.current.cur_prog = 0;
gc->state.current.cur_tex = 0;
gc->state.current.cur_texu = 0;
gc->state.current.cur_texv = 0;
gc->state.current.cur_texm = 0;
gc->state.current.cur_texmu = 0;
gc->state.current.cur_texmv = 0;
gc->state.current.render_op = 0;
gc->state.current.smooth = 0;
gc->state.current.blend = 0;
gc->state.current.clip = 0;
gc->state.current.cx = 0;
gc->state.current.cy = 0;
gc->state.current.cw = 0;
gc->state.current.ch = 0;
for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
{
gc->pipe[i].region.x = 0;
gc->pipe[i].region.y = 0;
gc->pipe[i].region.w = 0;
gc->pipe[i].region.h = 0;
gc->pipe[i].region.type = 0;
gc->pipe[i].clip.active = 0;
gc->pipe[i].clip.x = 0;
gc->pipe[i].clip.y = 0;
gc->pipe[i].clip.w = 0;
gc->pipe[i].clip.h = 0;
gc->pipe[i].shader.surface = NULL;
gc->pipe[i].shader.cur_prog = 0;
gc->pipe[i].shader.cur_tex = 0;
gc->pipe[i].shader.cur_texu = 0;
gc->pipe[i].shader.cur_texv = 0;
gc->pipe[i].shader.cur_texm = 0;
gc->pipe[i].shader.render_op = EVAS_RENDER_BLEND;
gc->pipe[i].shader.smooth = 0;
gc->pipe[i].shader.blend = 0;
gc->pipe[i].shader.clip = 0;
gc->pipe[i].shader.cx = 0;
gc->pipe[i].shader.cy = 0;
gc->pipe[i].shader.cw = 0;
gc->pipe[i].shader.ch = 0;
}
gc->change.size = 1;
glDisable(GL_SCISSOR_TEST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glScissor(0, 0, 0, 0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisable(GL_DEPTH_TEST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glEnable(GL_DITHER);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisable(GL_BLEND);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// no dest alpha
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
// glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
glDepthMask(GL_FALSE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
if (shared->info.anisotropic > 0.0)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
#endif
glEnableVertexAttribArray(SHAD_VERTEX);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glEnableVertexAttribArray(SHAD_COLOR);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(gc->shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glActiveTexture(GL_TEXTURE0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
_evas_gl_common_viewport_set(gc);
}
void
evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
{
if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
evas_gl_common_context_flush(gc);
gc->change.size = 1;
gc->rot = rot;
gc->w = w;
gc->h = h;
if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc);
}
void
evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc EINA_UNUSED,
int rot, int gw, int gh,
int cx, int cy, int cw, int ch,
int bitmask)
{
if (!glsym_glStartTiling) return;
switch (rot)
{
case 0: // UP this way: ^
glsym_glStartTiling(cx, cy, cw, ch, bitmask);
break;
case 90: // UP this way: <
glsym_glStartTiling(gh - (cy + ch), cx, ch, cw, bitmask);
break;
case 180: // UP this way: v
glsym_glStartTiling(gw - (cx + cw), gh - (cy + ch), cw, ch, bitmask);
break;
case 270: // UP this way: >
glsym_glStartTiling(cy, gw - (cx + cw), ch, cw, bitmask);
break;
default: // assume up is up
glsym_glStartTiling(cx, cy, cw, ch, bitmask);
break;
}
}
void
evas_gl_common_tiling_done(Evas_Engine_GL_Context *gc EINA_UNUSED)
{
if (glsym_glEndTiling)
{
glsym_glEndTiling(GL_COLOR_BUFFER_BIT0_QCOM);
}
}
void
evas_gl_common_context_done(Evas_Engine_GL_Context *gc)
{
if (gc->master_clip.used)
{
if (glsym_glEndTiling) glsym_glEndTiling(GL_COLOR_BUFFER_BIT0_QCOM);
gc->master_clip.used = EINA_FALSE;
}
}
void
evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc,
Evas_GL_Image *surface)
{
if (surface == gc->pipe[0].shader.surface) return;
evas_gl_common_context_flush(gc);
evas_gl_common_context_done(gc);
gc->state.current.cur_prog = PRG_INVALID;
gc->state.current.cur_tex = -1;
gc->state.current.cur_texu = -1;
gc->state.current.cur_texv = -1;
gc->state.current.render_op = -1;
gc->state.current.smooth = -1;
gc->state.current.blend = -1;
gc->state.current.clip = -1;
gc->state.current.cx = -1;
gc->state.current.cy = -1;
gc->state.current.cw = -1;
gc->state.current.ch = -1;
gc->pipe[0].shader.surface = surface;
gc->change.size = 1;
#ifdef GL_GLES
# ifndef GL_FRAMEBUFFER
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
# endif
#else
# ifndef GL_FRAMEBUFFER
# define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
# endif
#endif
if (gc->pipe[0].shader.surface == gc->def_surface)
{
glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
_evas_gl_common_viewport_set(gc);
}
#define PUSH_VERTEX(n, x, y, z) \
gc->pipe[n].array.vertex[nv++] = x; \
gc->pipe[n].array.vertex[nv++] = y; \
gc->pipe[n].array.vertex[nv++] = z
#define PUSH_COLOR(n, r, g, b, a) \
gc->pipe[n].array.color[nc++] = r; \
gc->pipe[n].array.color[nc++] = g; \
gc->pipe[n].array.color[nc++] = b; \
gc->pipe[n].array.color[nc++] = a
#define PUSH_TEXUV(n, u, v) \
gc->pipe[n].array.texuv[nu++] = u; \
gc->pipe[n].array.texuv[nu++] = v
#define PUSH_TEXUV2(n, u, v) \
gc->pipe[n].array.texuv2[nu2++] = u; \
gc->pipe[n].array.texuv2[nu2++] = v
#define PUSH_TEXUV3(n, u, v) \
gc->pipe[n].array.texuv3[nu3++] = u; \
gc->pipe[n].array.texuv3[nu3++] = v
#define PUSH_TEXM(n, u, v) \
gc->pipe[n].array.texm[nm++] = u; \
gc->pipe[n].array.texm[nm++] = v
#define PUSH_TEXSAM(n, x, y) \
gc->pipe[n].array.texsam[ns++] = x; \
gc->pipe[n].array.texsam[ns++] = y
static inline void
array_alloc(Evas_Engine_GL_Context *gc, int n)
{
gc->havestuff = EINA_TRUE;
if (gc->pipe[n].array.num <= gc->pipe[n].array.alloc)
{
#define ALOC(field, type, size) \
if ((gc->pipe[n].array.use_##field) && (!gc->pipe[n].array.field)) \
gc->pipe[n].array.field = \
malloc(gc->pipe[n].array.alloc * sizeof(type) * size)
ALOC(vertex, GLshort, 3);
ALOC(color, GLubyte, 4);
ALOC(texuv, GLfloat, 2);
ALOC(texm, GLfloat, 2);
ALOC(texuv2, GLfloat, 2);
ALOC(texuv3, GLfloat, 2);
ALOC(texsam, GLfloat, 2);
return;
}
gc->pipe[n].array.alloc += 6 * 1024;
#define RALOC(field, type, size) \
if (gc->pipe[n].array.use_##field) \
gc->pipe[n].array.field = realloc \
(gc->pipe[n].array.field, \
gc->pipe[n].array.alloc * sizeof(type) * size)
RALOC(vertex, GLshort, 3);
RALOC(color, GLubyte, 4);
RALOC(texuv, GLfloat, 2);
RALOC(texm, GLfloat, 2);
RALOC(texuv2, GLfloat, 2);
RALOC(texuv3, GLfloat, 2);
RALOC(texsam, GLfloat, 2);
}
#ifdef GLPIPES
static int
pipe_region_intersects(Evas_Engine_GL_Context *gc, int n,
int x, int y, int w, int h)
{
int rx, ry, rw, rh, ii, end;
const GLshort *v;
rx = gc->pipe[n].region.x;
ry = gc->pipe[n].region.y;
rw = gc->pipe[n].region.w;
rh = gc->pipe[n].region.h;
if (!RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh)) return 0;
// a hack for now. map pipes use their whole bounding box for intersects
// which at worst case reduces to old pipeline flushes, but cheaper than
// full quad region or triangle intersects right now
if (gc->pipe[n].region.type == RTYPE_MAP) return 1;
v = gc->pipe[n].array.vertex;
end = gc->pipe[n].array.num * 3;
for (ii = 0; ii < end; ii += (3 * 3 * 2))
{ // tri 1...
// 0, 1, 2 < top left
// 3, 4, 5 < top right
// 6, 7, 8 < bottom left
rx = v[ii + 0];
ry = v[ii + 1];
rw = v[ii + 3] - rx;
rh = v[ii + 7] - ry;
if (RECTS_INTERSECT(x, y, w, h, rx, ry, rw, rh)) return 1;
}
return 0;
}
#endif
static void
pipe_region_expand(Evas_Engine_GL_Context *gc, int n,
int x, int y, int w, int h)
{
int x1, y1, x2, y2;
if (gc->pipe[n].region.w <= 0)
{
gc->pipe[n].region.x = x;
gc->pipe[n].region.y = y;
gc->pipe[n].region.w = w;
gc->pipe[n].region.h = h;
return;
}
x1 = gc->pipe[n].region.x;
y1 = gc->pipe[n].region.y;
x2 = gc->pipe[n].region.x + gc->pipe[n].region.w;
y2 = gc->pipe[n].region.y + gc->pipe[n].region.h;
if (x < x1) x1 = x;
if (y < y1) y1 = y;
if ((x + w) > x2) x2 = x + w;
if ((y + h) > y2) y2 = y + h;
gc->pipe[n].region.x = x1;
gc->pipe[n].region.y = y1;
gc->pipe[n].region.w = x2 - x1;
gc->pipe[n].region.h = y2 - y1;
}
static Eina_Bool
vertex_array_size_check(Evas_Engine_GL_Context *gc EINA_UNUSED, int pn EINA_UNUSED, int n EINA_UNUSED)
{
return 1;
// this fixup breaks for expedite test 32. why?
/* for reference
if ((gc->pipe[pn].array.num + n) > gc->shared->info.max_vertex_elements)
{
shader_array_flush(gc);
return 0;
}
return 1;
*/
}
static inline Evas_GL_Shader
evas_gl_common_shader_choice(int npoints EINA_UNUSED,
RGBA_Map_Point *p,
int r, int g, int b, int a,
Evas_GL_Shader nomul,
Evas_GL_Shader mul)
{
if ((a == 255) && (r == 255) && (g == 255) && (b == 255))
{
if (!p) return nomul;
if ((p[0].col == 0xffffffff) && (p[1].col == 0xffffffff) &&
(p[2].col == 0xffffffff) && (p[3].col == 0xffffffff))
return nomul;
}
return mul;
}
static int
_evas_gl_common_context_push(int rtype,
Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
Evas_GL_Texture *texm,
GLuint prog,
int x, int y, int w, int h,
Eina_Bool blend,
Eina_Bool smooth,
Eina_Bool clip,
int cx, int cy, int cw, int ch)
{
GLuint current_tex = 0;
GLuint current_texm = 0;
int pn = 0;
if (tex)
current_tex = tex->ptt ? tex->ptt->texture : tex->pt->texture;
if (texm)
current_texm = texm->ptt ? texm->ptt->texture : texm->pt->texture;
#ifdef GLPIPES
again:
#endif
vertex_array_size_check(gc, gc->state.top_pipe, 6);
pn = gc->state.top_pipe;
#ifdef GLPIPES
if (!((pn == 0) && (gc->pipe[pn].array.num == 0)))
{
int found = 0;
int i;
for (i = pn; i >= 0; i--)
{
if ((gc->pipe[i].region.type == rtype)
&& (!tex || gc->pipe[i].shader.cur_tex == current_tex)
&& (!texm || gc->pipe[i].shader.cur_texm == current_texm)
&& (gc->pipe[i].shader.cur_prog == prog)
&& (gc->pipe[i].shader.smooth == smooth)
&& (gc->pipe[i].shader.blend == blend)
&& (gc->pipe[i].shader.render_op == gc->dc->render_op)
&& (gc->pipe[i].shader.clip == clip)
&& (!clip || ((gc->pipe[i].shader.cx == cx)
&& (gc->pipe[i].shader.cy == cy)
&& (gc->pipe[i].shader.cw == cw)
&& (gc->pipe[i].shader.ch == ch))))
{
found = 1;
pn = i;
break;
}
if (pipe_region_intersects(gc, i, x, y, w, h)) break;
}
if (!found)
{
pn = gc->state.top_pipe + 1;
if (pn >= gc->shared->info.tune.pipes.max)
{
shader_array_flush(gc);
goto again;
}
gc->state.top_pipe = pn;
}
}
if ((tex) && (((tex->im) && (tex->im->native.data)) || tex->pt->dyn.img))
{
if (gc->pipe[pn].array.im != tex->im)
{
shader_array_flush(gc);
pn = gc->state.top_pipe;
gc->pipe[pn].array.im = tex->im;
goto again;
}
}
#else
if (!((gc->pipe[pn].region.type == rtype)
&& (!tex || gc->pipe[pn].shader.cur_tex == current_tex)
&& (!texm || gc->pipe[pn].shader.cur_texm == current_texm)
&& (gc->pipe[pn].shader.cur_prog == prog)
&& (gc->pipe[pn].shader.smooth == smooth)
&& (gc->pipe[pn].shader.blend == blend)
&& (gc->pipe[pn].shader.render_op == gc->dc->render_op)
&& (gc->pipe[pn].shader.clip == clip)
&& (!clip || ((gc->pipe[pn].shader.cx == cx)
&& (gc->pipe[pn].shader.cy == cy)
&& (gc->pipe[pn].shader.cw == cw)
&& (gc->pipe[pn].shader.ch == ch)))))
{
shader_array_flush(gc);
}
if ((tex) && (((tex->im) && (tex->im->native.data)) || tex->pt->dyn.img))
{
if (gc->pipe[pn].array.im != tex->im)
{
shader_array_flush(gc);
gc->pipe[pn].array.im = tex->im;
}
}
#endif
return pn;
}
void
evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc,
int x1, int y1, int x2, int y2,
int clip, int cx, int cy, int cw, int ch,
int r, int g, int b, int a)
{
int pnum, nv, nc, i;
Eina_Bool blend = EINA_FALSE;
GLuint prog = gc->shared->shader[SHADER_RECT].prog;
int pn = 0;
if (!(gc->dc->render_op == EVAS_RENDER_COPY) && (a < 255))
blend = EINA_TRUE;
shader_array_flush(gc);
vertex_array_size_check(gc, gc->state.top_pipe, 2);
pn = gc->state.top_pipe;
gc->pipe[pn].shader.cur_tex = 0;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = clip;
gc->pipe[pn].shader.cx = cx;
gc->pipe[pn].shader.cy = cy;
gc->pipe[pn].shader.cw = cw;
gc->pipe[pn].shader.ch = ch;
gc->pipe[pn].array.line = 1;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 0;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4;
gc->pipe[pn].array.num += 2;
array_alloc(gc, pn);
PUSH_VERTEX(pn, x1, y1, 0);
PUSH_VERTEX(pn, x2, y2, 0);
for (i = 0; i < 2; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
shader_array_flush(gc);
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 0;
gc->pipe[pn].array.use_color = 0;
gc->pipe[pn].array.use_texuv = 0;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
}
void
evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
int x, int y, int w, int h,
int r, int g, int b, int a)
{
int pnum, nv, nc, i;
Eina_Bool blend = EINA_FALSE;
GLuint prog = gc->shared->shader[SHADER_RECT].prog;
int pn = 0;
if (!(gc->dc->render_op == EVAS_RENDER_COPY) && (a < 255))
blend = EINA_TRUE;
again:
vertex_array_size_check(gc, gc->state.top_pipe, 6);
pn = gc->state.top_pipe;
#ifdef GLPIPES
if ((pn == 0) && (gc->pipe[pn].array.num == 0))
{
gc->pipe[pn].region.type = RTYPE_RECT;
gc->pipe[pn].shader.cur_tex = 0;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 0;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
}
else
{
int found = 0;
for (i = pn; i >= 0; i--)
{
if ((gc->pipe[i].region.type == RTYPE_RECT)
&& (gc->pipe[i].shader.cur_tex == 0)
&& (gc->pipe[i].shader.cur_prog == prog)
&& (gc->pipe[i].shader.blend == blend)
&& (gc->pipe[i].shader.render_op == gc->dc->render_op)
&& (gc->pipe[i].shader.clip == 0)
)
{
found = 1;
pn = i;
break;
}
if (pipe_region_intersects(gc, i, x, y, w, h)) break;
}
if (!found)
{
pn = gc->state.top_pipe + 1;
if (pn >= gc->shared->info.tune.pipes.max)
{
shader_array_flush(gc);
goto again;
}
gc->state.top_pipe = pn;
gc->pipe[pn].region.type = RTYPE_RECT;
gc->pipe[pn].shader.cur_tex = 0;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 0;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
}
}
#else
if ((gc->pipe[pn].shader.cur_tex != 0)
|| (gc->pipe[pn].shader.cur_prog != prog)
|| (gc->pipe[pn].shader.blend != blend)
|| (gc->pipe[pn].shader.render_op != gc->dc->render_op)
|| (gc->pipe[pn].shader.clip != 0)
)
{
shader_array_flush(gc);
pn = gc->state.top_pipe;
gc->pipe[pn].shader.cur_tex = 0;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
}
gc->pipe[pn].region.type = RTYPE_RECT;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 0;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
#endif
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only)
{
Evas_GL_Texture_Pool *pt;
int pnum, nv, nc, nu, ns, i;
GLfloat tx1, tx2, ty1, ty2;
GLfloat offsetx, offsety;
Eina_Bool blend = EINA_FALSE;
GLuint prog = gc->shared->shader[SHADER_IMG].prog;
int pn = 0, sam = 0;
if (!(gc->dc->render_op == EVAS_RENDER_COPY) &&
((a < 255) || (tex->alpha))) blend = EINA_TRUE;
if (gc->filter_prog)
{
prog = gc->filter_prog;
}
else if (tex_only)
{
if (tex->pt->dyn.img)
{
if ((smooth) && ((sw >= (w * 2)) && (sh >= (h * 2))))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_22_BGRA_NOMUL, SHADER_IMG_22_BGRA)].prog;
sam = 1;
}
else if ((smooth) && (sw >= (w * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_21_BGRA_NOMUL, SHADER_IMG_21_BGRA)].prog;
sam = 1;
}
else if ((smooth) && (sh >= (h * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_12_BGRA_NOMUL, SHADER_IMG_12_BGRA)].prog;
sam = 1;
}
else
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
}
}
else
{
if ((smooth) && ((sw >= (w * 2)) && (sh >= (h * 2))))
{
if ((!tex->alpha) && (tex->pt->native))
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_22_NOMUL_AFILL, SHADER_TEX_22_AFILL)].prog;
else
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_22_NOMUL, SHADER_TEX_22)].prog;
sam = 1;
}
else if ((smooth) && (sw >= (w * 2)))
{
if ((!tex->alpha) && (tex->pt->native))
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_21_NOMUL_AFILL, SHADER_TEX_21_AFILL)].prog;
else
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_21_NOMUL, SHADER_TEX_21)].prog;
sam = 1;
}
else if ((smooth) && (sh >= (h * 2)))
{
if ((!tex->alpha) && (tex->pt->native))
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_12_NOMUL_AFILL, SHADER_TEX_12_AFILL)].prog;
else
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_12_NOMUL, SHADER_TEX_12)].prog;
sam = 1;
}
else
{
if ((!tex->alpha) && (tex->pt->native))
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_NOMUL_AFILL, SHADER_TEX_AFILL)].prog;
else
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_TEX_NOMUL, SHADER_TEX)].prog;
}
}
}
else
{
if (tex->gc->shared->info.bgra)
{
if ((smooth) && ((sw >= (w * 2)) && (sh >= (h * 2))))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_22_BGRA_NOMUL, SHADER_IMG_22_BGRA)].prog;
sam = 1;
}
else if ((smooth) && (sw >= (w * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_21_BGRA_NOMUL, SHADER_IMG_21_BGRA)].prog;
sam = 1;
}
else if ((smooth) && (sh >= (h * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_12_BGRA_NOMUL, SHADER_IMG_12_BGRA)].prog;
sam = 1;
}
else
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
}
}
else
{
if ((smooth) && ((sw >= (w * 2)) && (sh >= (h * 2))))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_22_NOMUL, SHADER_IMG_22)].prog;
sam = 1;
}
else if ((smooth) && (sw >= (w * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_21_NOMUL, SHADER_IMG_21)].prog;
sam = 1;
}
else if ((smooth) && (sh >= (h * 2)))
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_12_NOMUL, SHADER_IMG_12)].prog;
sam = 1;
}
else
{
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_IMG_NOMUL, SHADER_IMG)].prog;
}
}
}
if (tex->ptt)
{
pt = tex->ptt;
offsetx = tex->tx;
offsety = tex->ty;
// Adjusting sx, sy, sw and sh to real size of tiny texture
sx = sx * (EVAS_GL_TILE_SIZE - 2) / tex->w;
sw = sw * (EVAS_GL_TILE_SIZE - 2) / tex->w;
sy = sy * (EVAS_GL_TILE_SIZE - 1) / tex->h;
sh = sh * (EVAS_GL_TILE_SIZE - 1) / tex->h;
}
else
{
pt = tex->pt;
offsetx = tex->x;
offsety = tex->y;
}
pn = _evas_gl_common_context_push(RTYPE_IMAGE,
gc, tex, NULL,
prog,
x, y, w, h,
blend,
smooth,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_IMAGE;
gc->pipe[pn].shader.cur_tex = pt->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
// if nomul... dont need this
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = sam;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; ns = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
{
tx1 = ((double)(offsetx) + sx) / (double)pt->w;
ty1 = 1.0 - ((double)(offsety) + sy) / (double)pt->h;
tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
ty2 = 1.0 - ((double)(offsety) + sy + sh) / (double)pt->h;
}
else
{
tx1 = ((double)(offsetx) + sx) / (double)pt->w;
ty1 = ((double)(offsety) + sy) / (double)pt->h;
tx2 = ((double)(offsetx) + sx + sw) / (double)pt->w;
ty2 = ((double)(offsety) + sy + sh) / (double)pt->h;
}
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
if (sam)
{
double samx = (double)(sw) / (double)(tex->pt->w * w * 4);
double samy = (double)(sh) / (double)(tex->pt->h * h * 4);
PUSH_TEXSAM(pn, samx, samy);
PUSH_TEXSAM(pn, samx, samy);
PUSH_TEXSAM(pn, samx, samy);
PUSH_TEXSAM(pn, samx, samy);
PUSH_TEXSAM(pn, samx, samy);
PUSH_TEXSAM(pn, samx, samy);
}
// if nomul... dont need this
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_image_mask_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
Evas_GL_Texture *texm,
double sx, double sy, double sw, double sh,
double sxm, double sym, double swm,double shm,
int x, int y, int w, int h,
int r, int g, int b, int a,
Eina_Bool smooth)
{
int pnum, nv, nc, nu, nm, i;
GLfloat tx1, tx2, ty1, ty2;
GLfloat txm1, txm2, tym1, tym2;
Eina_Bool blend = 1;
GLuint prog = gc->shared->shader[SHADER_IMG_MASK].prog;
int pn = 0;
#if 0
if (tex->gc->shared->info.bgra)
{
prog = gc->shared->shader[SHADER_IMG_MASK].prog;
}
else
{
#warning Nash: FIXME: Need two shaders?
printf("Not good: Need other texture\n");
prog = gc->shared->shader[SHADER_IMG].prog;
}
#endif
pn = _evas_gl_common_context_push(RTYPE_IMASK,
gc, tex, texm,
prog,
x, y, w, h,
blend,
smooth,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_IMASK;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_texm = texm->pt->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
// if nomul... dont need this
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 1;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nm = pnum * 2; nu = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
{
tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
ty1 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
ty2 = ((double)(tex->y) + sy) / (double)tex->pt->h;
txm1 = ((double)(texm->x) + sxm) / (double)texm->pt->w;
tym1 = ((double)(texm->y) + sym + shm) / (double)texm->pt->h;
txm2 = ((double)(texm->x) + sxm + swm) / (double)texm->pt->w;
tym2 = ((double)(texm->y) + sym) / (double)texm->pt->h;
}
else
{
tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
txm1 = (texm->x + sxm) / (double)texm->pt->w;
tym1 = (texm->y + sym) / (double)texm->pt->h;
txm2 = (texm->x + sxm + swm) / (double)texm->pt->w;
tym2 = (texm->y + sym + shm) / (double)texm->pt->h;
}
// printf(" %3.6lf %3.6lf %3.6lf %3.6lf\n",sx,sy,sw,sh);
// printf("m%3.6lf %3.6lf %3.6lf %3.6lf\n",sxm,sym,swm,shm);
// printf(" %3f %3f %3f %3f\n",tx1,ty1,tx2,ty2);
// printf("m%3f %3f %3f %3f\n",txm1,tym1,txm2,tym2);
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXM(pn, txm1, tym1);
PUSH_TEXM(pn, txm2, tym1);
PUSH_TEXM(pn, txm1, tym2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXM(pn, txm2, tym1);
PUSH_TEXM(pn, txm2, tym2);
PUSH_TEXM(pn, txm1, tym2);
// if nomul... dont need this
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a)
{
int pnum, nv, nc, nu, i;
GLfloat tx1, tx2, ty1, ty2;
GLuint prog = gc->shared->shader[SHADER_FONT].prog;
int pn = 0;
pn = _evas_gl_common_context_push(RTYPE_FONT,
gc, tex, NULL,
prog,
x, y, w, h,
1,
0,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_FONT;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = 0;
gc->pipe[pn].shader.blend = 1;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
if (sw == 0.0)
{
tx1 = tex->sx1;
ty1 = tex->sy1;
tx2 = tex->sx2;
ty2 = tex->sy2;
}
else
{
tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
}
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Eina_Bool smooth)
{
int pnum, nv, nc, nu, nu2, nu3, i;
GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
Eina_Bool blend = 0;
GLuint prog;
int pn = 0;
if (a < 255) blend = 1;
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_YUV_NOMUL, SHADER_YUV)].prog;
pn = _evas_gl_common_context_push(RTYPE_YUV,
gc, tex, NULL,
prog,
x, y, w, h,
blend,
smooth,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_YUV;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 1;
gc->pipe[pn].array.use_texuv3 = 1;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
nu2 = pnum * 2; nu3 = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
tx1 = (sx) / (double)tex->pt->w;
ty1 = (sy) / (double)tex->pt->h;
tx2 = (sx + sw) / (double)tex->pt->w;
ty2 = (sy + sh) / (double)tex->pt->h;
t2x1 = ((sx) / 2) / (double)tex->ptu->w;
t2y1 = ((sy) / 2) / (double)tex->ptu->h;
t2x2 = ((sx + sw) / 2) / (double)tex->ptu->w;
t2y2 = ((sy + sh) / 2) / (double)tex->ptu->h;
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x1, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x1, t2y2);
PUSH_TEXUV3(pn, t2x1, t2y1);
PUSH_TEXUV3(pn, t2x2, t2y1);
PUSH_TEXUV3(pn, t2x1, t2y2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y2);
PUSH_TEXUV2(pn, t2x1, t2y2);
PUSH_TEXUV3(pn, t2x2, t2y1);
PUSH_TEXUV3(pn, t2x2, t2y2);
PUSH_TEXUV3(pn, t2x1, t2y2);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Eina_Bool smooth)
{
int pnum, nv, nc, nu, nu2, i;
GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
Eina_Bool blend = 0;
GLuint prog;
int pn = 0;
if (a < 255) blend = 1;
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_YUY2_NOMUL, SHADER_YUY2)].prog;
pn = _evas_gl_common_context_push(RTYPE_YUY2,
gc, tex, NULL,
prog,
x, y, w, h,
blend,
smooth,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_YUY2;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 1;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
nu2 = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
tx1 = (sx) / (double)tex->pt->w;
ty1 = (sy) / (double)tex->pt->h;
tx2 = (sx + sw) / (double)tex->pt->w;
ty2 = (sy + sh) / (double)tex->pt->h;
t2x1 = sx / (double)tex->ptuv->w;
t2y1 = sy / (double)tex->ptuv->h;
t2x2 = (sx + sw) / (double)tex->ptuv->w;
t2y2 = (sy + sh) / (double)tex->ptuv->h;
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x1, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x1, t2y2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y2);
PUSH_TEXUV2(pn, t2x1, t2y2);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Eina_Bool smooth)
{
int pnum, nv, nc, nu, nu2, i;
GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
Eina_Bool blend = 0;
GLuint prog;
int pn = 0;
if (a < 255) blend = 1;
prog = gc->shared->shader[evas_gl_common_shader_choice(0, NULL, r, g, b, a,
SHADER_NV12_NOMUL, SHADER_NV12)].prog;
pn = _evas_gl_common_context_push(RTYPE_NV12,
gc, tex, NULL,
prog,
x, y, w, h,
blend,
smooth,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_NV12;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_tex_dyn = tex->pt->dyn.img;
gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 1;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2;
nu2 = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
tx1 = (sx) / (double)tex->pt->w;
ty1 = (sy) / (double)tex->pt->h;
tx2 = (sx + sw) / (double)tex->pt->w;
ty2 = (sy + sh) / (double)tex->pt->h;
t2x1 = sx / (double)tex->ptuv->w;
t2y1 = sy / (double)tex->ptuv->h;
t2x2 = (sx + sw) / (double)tex->ptuv->w;
t2y2 = (sy + sh) / (double)tex->ptuv->h;
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x1, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x1, t2y2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXUV2(pn, t2x2, t2y1);
PUSH_TEXUV2(pn, t2x2, t2y2);
PUSH_TEXUV2(pn, t2x1, t2y2);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
int npoints,
RGBA_Map_Point *p,
int clip, int cx, int cy, int cw, int ch,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only,
Evas_Colorspace cspace)
{
int pnum, nv, nc, nu, nu2, nu3, i;
const int points[6] = { 0, 1, 2, 0, 2, 3 };
int x = 0, y = 0, w = 0, h = 0, px = 0, py = 0;
GLfloat tx[4], ty[4], t2x[4], t2y[4];
Eina_Bool blend = EINA_FALSE;
DATA32 cmul;
GLuint prog = gc->shared->shader[SHADER_IMG].prog;
Eina_Bool utexture = EINA_FALSE;
Eina_Bool uvtexture = EINA_FALSE;
int pn = 0;
int flat = 0;
if (!(gc->dc->render_op == EVAS_RENDER_COPY) &&
((a < 255) || (tex->alpha))) blend = EINA_TRUE;
if (npoints != 4)
{
// FIXME: nash - you didn't fix this for n points. its still all
// 4 point stuff!!! grrrr.
abort();
}
if ((A_VAL(&(p[0].col)) < 0xff) || (A_VAL(&(p[1].col)) < 0xff) ||
(A_VAL(&(p[2].col)) < 0xff) || (A_VAL(&(p[3].col)) < 0xff))
blend = 1;
if ((p[0].z == p[1].z) && (p[1].z == p[2].z) && (p[2].z == p[3].z))
flat = 1;
if (!clip) cx = cy = cw = ch = 0;
if (!flat)
{
if (p[0].foc <= 0) flat = 1;
}
switch (cspace)
{
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_YUV_NOMUL, SHADER_YUV)].prog;
utexture = EINA_TRUE;
break;
case EVAS_COLORSPACE_YCBCR422601_PL:
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_YUY2_NOMUL, SHADER_YUY2)].prog;
uvtexture = EINA_TRUE;
break;
case EVAS_COLORSPACE_YCBCR420NV12601_PL:
case EVAS_COLORSPACE_YCBCR420TM12601_PL:
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_NV12_NOMUL, SHADER_NV12)].prog;
uvtexture = EINA_TRUE;
break;
default:
if (tex_only)
{
if (tex->pt->dyn.img)
{
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_IMG_BGRA_NOMUL, SHADER_IMG_BGRA)].prog;
}
else
{
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_TEX_NOMUL, SHADER_TEX)].prog;
}
}
else
{
if (tex->gc->shared->info.bgra)
{
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_IMG_BGRA_NOMUL,
SHADER_IMG_BGRA)].prog;
}
else
{
prog = gc->shared->shader[evas_gl_common_shader_choice(npoints, p, r, g, b, a,
SHADER_IMG_NOMUL,
SHADER_IMG)].prog;
}
}
}
x = w = (p[0].x >> FP);
y = h = (p[0].y >> FP);
for (i = 0; i < 4; i++)
{
tx[i] = ((double)(tex->x) + (((double)p[i].u) / FP1)) /
(double)tex->pt->w;
ty[i] = ((double)(tex->y) + (((double)p[i].v) / FP1)) /
(double)tex->pt->h;
px = (p[i].x >> FP);
if (px < x) x = px;
else if (px > w) w = px;
py = (p[i].y >> FP);
if (py < y) y = py;
else if (py > h) h = py;
if (utexture)
{
t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptu->w;
t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptu->h;
}
else if (uvtexture)
{
t2x[i] = ((((double)p[i].u / 2) / FP1)) / (double)tex->ptuv->w;
t2y[i] = ((((double)p[i].v / 2) / FP1)) / (double)tex->ptuv->h;
}
}
w = w - x;
h = h - y;
if (!flat)
{
// FUZZZZ!
x -= 3;
y -= 3;
w += 6;
h += 6;
}
if (clip)
{
if (flat)
{
int nx = x, ny = y, nw = w, nh = h;
RECTS_CLIP_TO_RECT(nx, ny, nw, nh, cx, cy, cw, ch);
if ((nx == x) && (ny == y) && (nw == w) && (nh == h))
{
clip = 0; cx = 0; cy = 0; cw = 0; ch = 0;
}
x = nx; y = ny; w = nw; h = nh;
}
}
if (!flat)
{
shader_array_flush(gc);
gc->foc = p[0].foc >> FP;
gc->z0 = p[0].z0 >> FP;
gc->px = p[0].px >> FP;
gc->py = p[0].py >> FP;
gc->change.size = 1;
_evas_gl_common_viewport_set(gc);
}
pn = _evas_gl_common_context_push(RTYPE_MAP,
gc, tex, NULL,
prog,
x, y, w, h,
blend,
smooth,
clip, cx, cy, cw, ch);
gc->pipe[pn].region.type = RTYPE_MAP;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
if (utexture)
{
gc->pipe[pn].shader.cur_texu = tex->ptu->texture;
gc->pipe[pn].shader.cur_texu_dyn = tex->ptu->dyn.img;
gc->pipe[pn].shader.cur_texv = tex->ptv->texture;
gc->pipe[pn].shader.cur_texv_dyn = tex->ptv->dyn.img;
}
else if (uvtexture)
{
gc->pipe[pn].shader.cur_texu = tex->ptuv->texture;
gc->pipe[pn].shader.cur_texu_dyn = tex->ptuv->dyn.img;
}
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = blend;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = clip;
gc->pipe[pn].shader.cx = cx;
gc->pipe[pn].shader.cy = cy;
gc->pipe[pn].shader.cw = cw;
gc->pipe[pn].shader.ch = ch;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = (utexture || uvtexture) ? 1 : 0;
gc->pipe[pn].array.use_texuv3 = (utexture) ? 1 : 0;
gc->pipe[pn].array.use_texm = 0;
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nu2 = pnum * 2;
nu2 = pnum * 2; nu3 = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
if ((tex->im) && (tex->im->native.data) && (!tex->im->native.yinvert))
{
for (i = 0; i < 4; i++)
{
ty[i] = 1.0 - ty[i];
if (utexture || uvtexture)
t2y[i] = 1.0 - t2y[i];
}
}
cmul = ARGB_JOIN(a, r, g, b);
for (i = 0; i < 6; i++)
{
DATA32 cl = MUL4_SYM(cmul, p[points[i]].col);
if (flat)
{
PUSH_VERTEX(pn,
(p[points[i]].x >> FP),
(p[points[i]].y >> FP),
0);
}
else
{
PUSH_VERTEX(pn,
(p[points[i]].fx) + gc->shared->ax,
(p[points[i]].fy) + gc->shared->ay,
(p[points[i]].fz)
+ (gc->shared->foc - gc->shared->z0));
}
PUSH_TEXUV(pn,
tx[points[i]],
ty[points[i]]);
if (utexture)
{
PUSH_TEXUV2(pn,
t2x[points[i]],
t2y[points[i]]);
PUSH_TEXUV3(pn,
t2x[points[i]],
t2y[points[i]]);
}
else if (uvtexture)
{
PUSH_TEXUV2(pn,
t2x[points[i]],
t2y[points[i]]);
}
PUSH_COLOR(pn,
R_VAL(&cl),
G_VAL(&cl),
B_VAL(&cl),
A_VAL(&cl));
}
if (!flat)
{
shader_array_flush(gc);
gc->foc = 0;
gc->z0 = 0;
gc->px = 0;
gc->py = 0;
gc->change.size = 1;
_evas_gl_common_viewport_set(gc);
}
}
void
evas_gl_common_context_flush(Evas_Engine_GL_Context *gc)
{
shader_array_flush(gc);
}
static void
scissor_rot(Evas_Engine_GL_Context *gc EINA_UNUSED,
int rot, int gw, int gh, int cx, int cy, int cw, int ch)
{
switch (rot)
{
case 0: // UP this way: ^
glScissor(cx, cy, cw, ch);
break;
case 90: // UP this way: <
glScissor(gh - (cy + ch), cx, ch, cw);
break;
case 180: // UP this way: v
glScissor(gw - (cx + cw), gh - (cy + ch), cw, ch);
break;
case 270: // UP this way: >
glScissor(cy, gw - (cx + cw), ch, cw);
break;
default: // assume up is up
glScissor(cx, cy, cw, ch);
break;
}
}
static void
start_tiling(Evas_Engine_GL_Context *gc EINA_UNUSED,
int rot, int gw, int gh, int cx, int cy, int cw, int ch,
int bitmask)
{
if (!glsym_glStartTiling) return;
switch (rot)
{
case 0: // UP this way: ^
glsym_glStartTiling(cx, cy, cw, ch, bitmask);
break;
case 90: // UP this way: <
glsym_glStartTiling(gh - (cy + ch), cx, ch, cw, bitmask);
break;
case 180: // UP this way: v
glsym_glStartTiling(gw - (cx + cw), gh - (cy + ch), cw, ch, bitmask);
break;
case 270: // UP this way: >
glsym_glStartTiling(cy, gw - (cx + cw), ch, cw, bitmask);
break;
default: // assume up is up
glsym_glStartTiling(cx, cy, cw, ch, bitmask);
break;
}
}
static void
shader_array_flush(Evas_Engine_GL_Context *gc)
{
int i, gw, gh, setclip, fbo = 0, done = 0;
if (!gc->havestuff) return;
gw = gc->w;
gh = gc->h;
if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
(!gc->pipe[0].shader.surface)))
{
gw = gc->pipe[0].shader.surface->w;
gh = gc->pipe[0].shader.surface->h;
fbo = 1;
}
for (i = 0; i < gc->shared->info.tune.pipes.max; i++)
{
if (gc->pipe[i].array.num <= 0) break;
setclip = 0;
done++;
gc->flushnum++;
GLERR(__FUNCTION__, __FILE__, __LINE__, "<flush err>");
if (gc->pipe[i].shader.cur_prog != gc->state.current.cur_prog)
{
glUseProgram(gc->pipe[i].shader.cur_prog);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex)
{
#if 0
if (gc->pipe[i].shader.cur_tex)
{
glEnable(GL_TEXTURE_2D);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisable(GL_TEXTURE_2D);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
#endif
glActiveTexture(GL_TEXTURE0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_tex);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->pipe[i].array.im)
{
#ifdef GL_GLES
if (gc->pipe[i].array.im->tex->pt->dyn.img)
{
secsym_glEGLImageTargetTexture2DOES
(GL_TEXTURE_2D, gc->pipe[i].array.im->tex->pt->dyn.img);
}
else
#endif
{
if (!gc->pipe[i].array.im->native.loose)
{
if (gc->pipe[i].array.im->native.func.bind)
gc->pipe[i].array.im->native.func.bind(gc->pipe[i].array.im->native.func.data,
gc->pipe[i].array.im);
}
}
}
if (gc->pipe[i].shader.render_op != gc->state.current.render_op)
{
switch (gc->pipe[i].shader.render_op)
{
case EVAS_RENDER_BLEND: /**< default op: d = d*(1-sa) + s */
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
break;
case EVAS_RENDER_COPY: /**< d = s */
gc->pipe[i].shader.blend = 0;
glBlendFunc(GL_ONE, GL_ONE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
break;
// FIXME: fix blend funcs below!
case EVAS_RENDER_BLEND_REL: /**< d = d*(1 - sa) + s*da */
case EVAS_RENDER_COPY_REL: /**< d = s*da */
case EVAS_RENDER_ADD: /**< d = d + s */
case EVAS_RENDER_ADD_REL: /**< d = d + s*da */
case EVAS_RENDER_SUB: /**< d = d - s */
case EVAS_RENDER_SUB_REL: /**< d = d - s*da */
case EVAS_RENDER_TINT: /**< d = d*s + d*(1 - sa) + s*(1 - da) */
case EVAS_RENDER_TINT_REL: /**< d = d*(1 - sa + s) */
case EVAS_RENDER_MASK: /**< d = d*sa */
case EVAS_RENDER_MUL: /**< d = d*s */
default:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
break;
}
}
if (gc->pipe[i].shader.blend != gc->state.current.blend)
{
if (gc->pipe[i].shader.blend)
{
glEnable(GL_BLEND);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisable(GL_BLEND);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
}
if ((gc->pipe[i].shader.smooth != gc->state.current.smooth) ||
(gc->pipe[i].shader.cur_tex != gc->state.current.cur_tex))
{
if (gc->pipe[i].shader.smooth)
{
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
if (shared->info.anisotropic > 0.0)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, shared->info.anisotropic);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
if (shared->info.anisotropic > 0.0)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
}
if (gc->pipe[i].shader.clip != gc->state.current.clip)
{
int cx, cy, cw, ch;
cx = gc->pipe[i].shader.cx;
cy = gc->pipe[i].shader.cy;
cw = gc->pipe[i].shader.cw;
ch = gc->pipe[i].shader.ch;
if ((gc->master_clip.enabled) && (!fbo))
{
if (gc->pipe[i].shader.clip)
{
RECTS_CLIP_TO_RECT(cx, cy, cw, ch,
gc->master_clip.x, gc->master_clip.y,
gc->master_clip.w, gc->master_clip.h);
}
else
{
cx = gc->master_clip.x;
cy = gc->master_clip.y;
cw = gc->master_clip.w;
ch = gc->master_clip.h;
}
}
if ((glsym_glStartTiling) && (glsym_glEndTiling) &&
(gc->master_clip.enabled) &&
(gc->master_clip.w > 0) && (gc->master_clip.h > 0))
{
if (!gc->master_clip.used)
{
if (!fbo)
{
start_tiling(gc, gc->rot, gw, gh,
gc->master_clip.x,
gh - gc->master_clip.y - gc->master_clip.h,
gc->master_clip.w, gc->master_clip.h,
gc->preserve_bit);
if (!gc->preserve_bit)
gc->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
}
else
start_tiling(gc, 0, gw, gh,
gc->master_clip.x, gc->master_clip.y,
gc->master_clip.w, gc->master_clip.h, 0);
gc->master_clip.used = EINA_TRUE;
}
}
if ((gc->pipe[i].shader.clip) ||
((gc->master_clip.enabled) && (!fbo)))
{
glEnable(GL_SCISSOR_TEST);
if (!fbo)
scissor_rot(gc, gc->rot, gw, gh, cx, gh - cy - ch, cw, ch);
else
glScissor(cx, cy, cw, ch);
setclip = 1;
gc->state.current.cx = cx;
gc->state.current.cy = cy;
gc->state.current.cw = cw;
gc->state.current.ch = ch;
}
else
{
glDisable(GL_SCISSOR_TEST);
glScissor(0, 0, 0, 0);
gc->state.current.cx = 0;
gc->state.current.cy = 0;
gc->state.current.cw = 0;
gc->state.current.ch = 0;
}
}
if (((gc->pipe[i].shader.clip) && (!setclip)) ||
((gc->master_clip.enabled) && (!fbo)))
{
int cx, cy, cw, ch;
cx = gc->pipe[i].shader.cx;
cy = gc->pipe[i].shader.cy;
cw = gc->pipe[i].shader.cw;
ch = gc->pipe[i].shader.ch;
if ((gc->master_clip.enabled) && (!fbo))
{
if (gc->pipe[i].shader.clip)
{
RECTS_CLIP_TO_RECT(cx, cy, cw, ch,
gc->master_clip.x, gc->master_clip.y,
gc->master_clip.w, gc->master_clip.h);
}
else
{
cx = gc->master_clip.x;
cy = gc->master_clip.y;
cw = gc->master_clip.w;
ch = gc->master_clip.h;
}
}
if ((cx != gc->state.current.cx) ||
(cy != gc->state.current.cy) ||
(cw != gc->state.current.cw) ||
(ch != gc->state.current.ch))
{
if (!fbo)
scissor_rot(gc, gc->rot, gw, gh, cx, gh - cy - ch, cw, ch);
else
glScissor(cx, cy, cw, ch);
gc->state.current.cx = cx;
gc->state.current.cy = cy;
gc->state.current.cw = cw;
gc->state.current.ch = ch;
}
}
unsigned char *vertex_ptr = NULL;
unsigned char *color_ptr = NULL;
unsigned char *texuv_ptr = NULL;
unsigned char *texuv2_ptr = NULL;
unsigned char *texuv3_ptr = NULL;
unsigned char *texm_ptr = NULL;
unsigned char *texsam_ptr = NULL;
if (glsym_glMapBuffer && glsym_glUnmapBuffer)
{
unsigned char *x;
# define VERTEX_SIZE (gc->pipe[i].array.num * sizeof(GLshort) * 3)
# define COLOR_SIZE (gc->pipe[i].array.num * sizeof(GLubyte) * 4)
# define TEX_SIZE (gc->pipe[i].array.num * sizeof(GLfloat) * 2)
vertex_ptr = NULL;
color_ptr = vertex_ptr + VERTEX_SIZE;
texuv_ptr = color_ptr + COLOR_SIZE;
texuv2_ptr = texuv_ptr + TEX_SIZE;
texuv3_ptr = texuv2_ptr + TEX_SIZE;
texm_ptr = texuv3_ptr + TEX_SIZE;
texsam_ptr = texm_ptr + TEX_SIZE;
# define END_POINTER (texsam_ptr + TEX_SIZE)
glBindBuffer(GL_ARRAY_BUFFER, gc->pipe[i].array.buffer);
if ((gc->pipe[i].array.buffer_alloc < (long)END_POINTER) ||
(gc->pipe[i].array.buffer_use >= (ARRAY_BUFFER_USE + ARRAY_BUFFER_USE_SHIFT * i)))
{
glBufferData(GL_ARRAY_BUFFER, (long)END_POINTER, NULL, GL_STATIC_DRAW);
gc->pipe[i].array.buffer_alloc = (long)END_POINTER;
gc->pipe[i].array.buffer_use = 0;
}
gc->pipe[i].array.buffer_use++;
x = glsym_glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
if (x)
{
if (gc->pipe[i].array.use_vertex)
memcpy(x + (unsigned long)vertex_ptr, gc->pipe[i].array.vertex, VERTEX_SIZE);
if (gc->pipe[i].array.use_color)
memcpy(x + (unsigned long)color_ptr, gc->pipe[i].array.color, COLOR_SIZE);
if (gc->pipe[i].array.use_texuv)
memcpy(x + (unsigned long)texuv_ptr, gc->pipe[i].array.texuv, TEX_SIZE);
if (gc->pipe[i].array.use_texuv2)
memcpy(x + (unsigned long)texuv2_ptr, gc->pipe[i].array.texuv2, TEX_SIZE);
if (gc->pipe[i].array.use_texuv3)
memcpy(x + (unsigned long)texuv3_ptr, gc->pipe[i].array.texuv3, TEX_SIZE);
if (gc->pipe[i].array.use_texm)
memcpy(x + (unsigned long)texm_ptr, gc->pipe[i].array.texm, TEX_SIZE);
if (gc->pipe[i].array.use_texsam)
memcpy(x + (unsigned long)texsam_ptr, gc->pipe[i].array.texsam, TEX_SIZE);
/*
fprintf(stderr, "copy %i bytes [%i/%i slots] [%i + %i + %i + %i + %i + %i + %i] <%i %i %i %i %i %i %i>\n",
(int)((unsigned char *)END_POINTER),
gc->pipe[i].array.num,
gc->pipe[i].array.alloc,
VERTEX_SIZE, COLOR_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE, TEX_SIZE,
gc->pipe[i].array.use_vertex,
gc->pipe[i].array.use_color,
gc->pipe[i].array.use_texuv,
gc->pipe[i].array.use_texuv2,
gc->pipe[i].array.use_texuv3,
gc->pipe[i].array.use_texm,
gc->pipe[i].array.use_texsam);
*/
glsym_glUnmapBuffer(GL_ARRAY_BUFFER);
}
}
else
{
vertex_ptr = (unsigned char *)gc->pipe[i].array.vertex;
color_ptr = (unsigned char *)gc->pipe[i].array.color;
texuv_ptr = (unsigned char *)gc->pipe[i].array.texuv;
texuv2_ptr = (unsigned char *)gc->pipe[i].array.texuv2;
texuv3_ptr = (unsigned char *)gc->pipe[i].array.texuv3;
texm_ptr = (unsigned char *)gc->pipe[i].array.texm;
texsam_ptr = (unsigned char *)gc->pipe[i].array.texsam;
}
glVertexAttribPointer(SHAD_VERTEX, 3, GL_SHORT, GL_FALSE, 0, (void *)vertex_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void *)color_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (gc->pipe[i].array.line)
{
glDisableVertexAttribArray(SHAD_TEXUV);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisableVertexAttribArray(SHAD_TEXUV2);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisableVertexAttribArray(SHAD_TEXUV3);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDrawArrays(GL_LINES, 0, gc->pipe[i].array.num);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
if (gc->pipe[i].array.use_texuv)
{
glEnableVertexAttribArray(SHAD_TEXUV);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0,
(void *)texuv_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisableVertexAttribArray(SHAD_TEXUV);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->pipe[i].array.use_texm)
{
glEnableVertexAttribArray(SHAD_TEXM);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXM, 2, GL_FLOAT, GL_FALSE, 0, (void *)texm_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glActiveTexture(GL_TEXTURE1);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texm);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glActiveTexture(GL_TEXTURE0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisableVertexAttribArray(SHAD_TEXM);
}
if (gc->pipe[i].array.use_texsam)
{
glEnableVertexAttribArray(SHAD_TEXSAM);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXSAM, 2, GL_FLOAT, GL_FALSE, 0, (void *)texsam_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisableVertexAttribArray(SHAD_TEXSAM);
}
if ((gc->pipe[i].array.use_texuv2) && (gc->pipe[i].array.use_texuv3))
{
glEnableVertexAttribArray(SHAD_TEXUV2);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glEnableVertexAttribArray(SHAD_TEXUV3);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, (void *)texuv2_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXUV3, 2, GL_FLOAT, GL_FALSE, 0, (void *)texuv3_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glActiveTexture(GL_TEXTURE1);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
#ifdef GL_GLES
if (gc->pipe[i].shader.cur_texu_dyn)
secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
#endif
glActiveTexture(GL_TEXTURE2);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
#ifdef GL_GLES
if (gc->pipe[i].shader.cur_texv_dyn)
secsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texv_dyn);
#endif
glActiveTexture(GL_TEXTURE0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else if (gc->pipe[i].array.use_texuv2)
{
glEnableVertexAttribArray(SHAD_TEXUV2);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glVertexAttribPointer(SHAD_TEXUV2, 2, GL_FLOAT, GL_FALSE, 0, (void *)texuv2_ptr);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glActiveTexture(GL_TEXTURE1);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glBindTexture(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
#ifdef GL_GLES
if (gc->pipe[i].shader.cur_texu_dyn)
secsym_glEGLImageTargetTexture2DOES
(GL_TEXTURE_2D, gc->pipe[i].shader.cur_texu_dyn);
#endif
glActiveTexture(GL_TEXTURE0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
else
{
glDisableVertexAttribArray(SHAD_TEXUV2);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
glDisableVertexAttribArray(SHAD_TEXUV3);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (dbgflushnum)
{
const char *types[6] =
{"----", "RECT", "IMAG", "FONT", "YUV-", "MAP"};
printf(" DRAW#%3i %4i -> %p[%4ix%4i] @ %4ix%4i -{ tex %4i type %s }-\n",
i,
gc->pipe[i].array.num / 6,
gc->pipe[0].shader.surface,
gc->pipe[0].shader.surface->w,
gc->pipe[0].shader.surface->h,
gw, gh,
gc->pipe[i].shader.cur_tex,
types[gc->pipe[i].region.type]
);
}
glDrawArrays(GL_TRIANGLES, 0, gc->pipe[i].array.num);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->pipe[i].array.im)
{
if (!gc->pipe[i].array.im->native.loose)
{
if (gc->pipe[i].array.im->native.func.unbind)
gc->pipe[i].array.im->native.func.unbind(gc->pipe[i].array.im->native.func.data,
gc->pipe[i].array.im);
}
gc->pipe[i].array.im = NULL;
}
gc->state.current.cur_prog = gc->pipe[i].shader.cur_prog;
gc->state.current.cur_tex = gc->pipe[i].shader.cur_tex;
gc->state.current.render_op = gc->pipe[i].shader.render_op;
// gc->state.current.cx = gc->pipe[i].shader.cx;
// gc->state.current.cy = gc->pipe[i].shader.cy;
// gc->state.current.cw = gc->pipe[i].shader.cw;
// gc->state.current.ch = gc->pipe[i].shader.ch;
gc->state.current.smooth = gc->pipe[i].shader.smooth;
gc->state.current.blend = gc->pipe[i].shader.blend;
gc->state.current.clip = gc->pipe[i].shader.clip;
if (gc->pipe[i].array.vertex) free(gc->pipe[i].array.vertex);
if (gc->pipe[i].array.color) free(gc->pipe[i].array.color);
if (gc->pipe[i].array.texuv) free(gc->pipe[i].array.texuv);
if (gc->pipe[i].array.texm) free(gc->pipe[i].array.texm);
if (gc->pipe[i].array.texuv2) free(gc->pipe[i].array.texuv2);
if (gc->pipe[i].array.texuv3) free(gc->pipe[i].array.texuv3);
if (gc->pipe[i].array.texsam) free(gc->pipe[i].array.texsam);
gc->pipe[i].array.line = 0;
gc->pipe[i].array.use_vertex = 0;
gc->pipe[i].array.use_color = 0;
gc->pipe[i].array.use_texuv = 0;
gc->pipe[i].array.use_texuv2 = 0;
gc->pipe[i].array.use_texuv3 = 0;
gc->pipe[i].array.use_texm = 0;
gc->pipe[i].array.use_texsam = 0;
gc->pipe[i].array.vertex = NULL;
gc->pipe[i].array.color = NULL;
gc->pipe[i].array.texuv = NULL;
gc->pipe[i].array.texm = NULL;
gc->pipe[i].array.texuv2 = NULL;
gc->pipe[i].array.texuv3 = NULL;
gc->pipe[i].array.texsam = NULL;
gc->pipe[i].array.num = 0;
gc->pipe[i].array.alloc = 0;
if (glsym_glMapBuffer && glsym_glUnmapBuffer)
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
gc->pipe[i].region.x = 0;
gc->pipe[i].region.y = 0;
gc->pipe[i].region.w = 0;
gc->pipe[i].region.h = 0;
gc->pipe[i].region.type = 0;
}
gc->state.top_pipe = 0;
if (dbgflushnum)
{
if (done > 0) printf("DONE (pipes): %i\n", done);
}
gc->havestuff = EINA_FALSE;
}
int
evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* buf_name, int frame, const char *suffix)
{
RGBA_Image *im = NULL;
DATA32 *data1, *data2;
char fname[100];
int ok = 0;
sprintf(fname, "./%s/win_%s-fc_%03d_%s.png", dname, buf_name, frame, suffix);
data1 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
data2 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
if ((!data1) || (!data2)) goto finish;
glReadPixels(0, 0, gc->w, gc->h, GL_RGBA,
GL_UNSIGNED_BYTE, (unsigned char*)data1);
// Flip the Y and change from RGBA TO BGRA
int i, j;
for (j = 0; j < gc->h; j++)
for (i = 0; i < gc->w; i++)
{
DATA32 d;
int idx1 = (j * gc->w) + i;
int idx2 = ((gc->h - 1) - j) * gc->w + i;
d = data1[idx1];
data2[idx2] = ((d & 0x000000ff) << 16) +
((d & 0x00ff0000) >> 16) +
((d & 0xff00ff00));
}
evas_common_convert_argb_premul(data2, gc->w * gc->h);
im = (RGBA_Image*) evas_cache_image_data(evas_common_image_cache_get(),
gc->w,
gc->h,
(DATA32 *)data2,
1,
EVAS_COLORSPACE_ARGB8888);
if (im)
{
im->image.data = data2;
if (im->image.data)
{
ok = evas_common_save_image_to_file(im, fname, NULL, 0, 0);
if (!ok) ERR("Error Saving file.");
}
evas_cache_image_drop(&im->cache_entry);
}
finish:
if (data1) free(data1);
if (data2) free(data2);
if (im) evas_cache_image_drop(&im->cache_entry);
if (ok) return 1;
else return 0;
}
Eina_Bool
evas_gl_common_module_open(void)
{
if (_evas_engine_GL_common_log_dom < 0)
_evas_engine_GL_common_log_dom = eina_log_domain_register
("evas-gl_common", EVAS_DEFAULT_LOG_COLOR);
if (_evas_engine_GL_common_log_dom < 0)
{
EINA_LOG_ERR("Can not create a module log domain.");
return EINA_FALSE;
}
return EINA_TRUE;
}
void
evas_gl_common_module_close(void)
{
if (_evas_engine_GL_common_log_dom < 0) return;
eina_log_domain_unregister(_evas_engine_GL_common_log_dom);
_evas_engine_GL_common_log_dom = -1;
}