Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Paste
P219
gl test
Active
Public
Actions
Authored by
zmike
on May 31 2018, 4:13 AM.
Edit Paste
Archive Paste
View Raw File
Subscribe
Mute Notifications
Award Token
Flag For Later
Tags
efl
Subscribers
None
/**
* Example of working with OpenGL APIs in Evas.
*
* Evas_GL.h should be added for Evas GL APIs access.
*
* @verbatim
* gcc -o evas-gl evas-gl.c `pkg-config --libs --cflags evas ecore ecore-evas` -lm
* @endverbatim
*/
#include
<Ecore.h>
#include
<Ecore_Evas.h>
#include
<Evas_GL.h>
#include
<math.h>
#define WIDTH 500
#define HEIGHT 500
//GL related data here...
typedef
struct
_GLData
{
Evas_Object
*
win
;
Evas_GL
*
evasgl
;
Evas_GL_API
*
glapi
;
Evas_GL_Context
*
ctx
;
Evas_GL_Surface
*
sfc
;
Evas_Object
*
img
;
unsigned
int
program
;
unsigned
int
vtx_shader
;
unsigned
int
fgmt_shader
;
unsigned
int
vbo
;
float
view
[
16
];
float
xangle
;
float
yangle
;
Eina_Bool
mouse_down
:
1
;
Eina_Bool
initialized
:
1
;
}
GLData
;
static
GLData
gldata
;
//Define the cube's vertices
//Each vertex consist of x, y, z, r, g, b
const
float
cube_vertices
[]
=
{
//front surface is blue
0.5
,
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
-
0.5
,
-
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
0.5
,
-
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
0.5
,
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
-
0.5
,
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
-
0.5
,
-
0.5
,
0.5
,
0.0
,
0.0
,
1.0
,
//left surface is green
-
0.5
,
0.5
,
0.5
,
0.0
,
1.0
,
0.0
,
-
0.5
,
-
0.5
,
-
0.5
,
0.0
,
1.0
,
0.0
,
-
0.5
,
-
0.5
,
0.5
,
0.0
,
1.0
,
0.0
,
-
0.5
,
0.5
,
0.5
,
0.0
,
1.0
,
0.0
,
-
0.5
,
0.5
,
-
0.5
,
0.0
,
1.0
,
0.0
,
-
0.5
,
-
0.5
,
-
0.5
,
0.0
,
1.0
,
0.0
,
//top surface is red
-
0.5
,
0.5
,
0.5
,
1.0
,
0.0
,
0.0
,
0.5
,
0.5
,
-
0.5
,
1.0
,
0.0
,
0.0
,
-
0.5
,
0.5
,
-
0.5
,
1.0
,
0.0
,
0.0
,
-
0.5
,
0.5
,
0.5
,
1.0
,
0.0
,
0.0
,
0.5
,
0.5
,
0.5
,
1.0
,
0.0
,
0.0
,
0.5
,
0.5
,
-
0.5
,
1.0
,
0.0
,
0.0
,
//right surface is yellow
0.5
,
0.5
,
-
0.5
,
1.0
,
1.0
,
0.0
,
0.5
,
-
0.5
,
0.5
,
1.0
,
1.0
,
0.0
,
0.5
,
-
0.5
,
-
0.5
,
1.0
,
1.0
,
0.0
,
0.5
,
0.5
,
-
0.5
,
1.0
,
1.0
,
0.0
,
0.5
,
0.5
,
0.5
,
1.0
,
1.0
,
0.0
,
0.5
,
-
0.5
,
0.5
,
1.0
,
1.0
,
0.0
,
//back surface is cyan
-
0.5
,
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
0.5
,
-
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
-
0.5
,
-
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
-
0.5
,
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
0.5
,
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
0.5
,
-
0.5
,
-
0.5
,
0.0
,
1.0
,
1.0
,
//bottom surface is magenta
-
0.5
,
-
0.5
,
-
0.5
,
1.0
,
0.0
,
1.0
,
0.5
,
-
0.5
,
0.5
,
1.0
,
0.0
,
1.0
,
-
0.5
,
-
0.5
,
0.5
,
1.0
,
0.0
,
1.0
,
-
0.5
,
-
0.5
,
-
0.5
,
1.0
,
0.0
,
1.0
,
0.5
,
-
0.5
,
-
0.5
,
1.0
,
0.0
,
1.0
,
0.5
,
-
0.5
,
0.5
,
1.0
,
0.0
,
1.0
};
//Vertext Shader Source
static
const
char
vertex_shader
[]
=
"attribute vec4 vPosition;
\n
"
"attribute vec3 inColor;
\n
"
"uniform mat4 mvpMatrix;"
"varying vec3 outColor;
\n
"
"void main()
\n
"
"{
\n
"
" outColor = inColor;
\n
"
" gl_Position = mvpMatrix * vPosition;
\n
"
"}
\n
"
;
//Fragment Shader Source
static
const
char
fragment_shader
[]
=
"#ifdef GL_ES
\n
"
"precision mediump float;
\n
"
"#endif
\n
"
"varying vec3 outColor;
\n
"
"void main()
\n
"
"{
\n
"
" gl_FragColor = vec4 ( outColor, 1.0 );
\n
"
"}
\n
"
;
//Rotation Operation related functions here...
static
void
init_matrix
(
float
matrix
[
16
])
{
matrix
[
0
]
=
1.0f
;
matrix
[
1
]
=
0.0f
;
matrix
[
2
]
=
0.0f
;
matrix
[
3
]
=
0.0f
;
matrix
[
4
]
=
0.0f
;
matrix
[
5
]
=
1.0f
;
matrix
[
6
]
=
0.0f
;
matrix
[
7
]
=
0.0f
;
matrix
[
8
]
=
0.0f
;
matrix
[
9
]
=
0.0f
;
matrix
[
10
]
=
1.0f
;
matrix
[
11
]
=
0.0f
;
matrix
[
12
]
=
0.0f
;
matrix
[
13
]
=
0.0f
;
matrix
[
14
]
=
0.0f
;
matrix
[
15
]
=
1.0f
;
}
static
void
multiply_matrix
(
float
matrix
[
16
],
const
float
matrix0
[
16
],
const
float
matrix1
[
16
])
{
int
i
;
int
row
;
int
column
;
float
temp
[
16
];
for
(
column
=
0
;
column
<
4
;
column
++
)
{
for
(
row
=
0
;
row
<
4
;
row
++
)
{
temp
[(
column
*
4
)
+
row
]
=
0.0f
;
for
(
i
=
0
;
i
<
4
;
i
++
)
temp
[(
column
*
4
)
+
row
]
+=
matrix0
[(
i
*
4
)
+
row
]
*
matrix1
[(
column
*
4
)
+
i
];
}
}
for
(
i
=
0
;
i
<
16
;
i
++
)
matrix
[
i
]
=
temp
[
i
];
}
static
void
rotate_xyz
(
float
matrix
[
16
],
const
float
anglex
,
const
float
angley
,
const
float
anglez
)
{
const
float
pi
=
3.141592f
;
float
temp
[
16
];
float
rx
=
2.0f
*
pi
*
anglex
/
360.0f
;
float
ry
=
2.0f
*
pi
*
angley
/
360.0f
;
float
rz
=
2.0f
*
pi
*
anglez
/
360.0f
;
float
sy
=
sinf
(
ry
);
float
cy
=
cosf
(
ry
);
float
sx
=
sinf
(
rx
);
float
cx
=
cosf
(
rx
);
float
sz
=
sinf
(
rz
);
float
cz
=
cosf
(
rz
);
init_matrix
(
temp
);
temp
[
0
]
=
(
cy
*
cz
)
-
(
sx
*
sy
*
sz
);
temp
[
1
]
=
(
cz
*
sx
*
sy
)
+
(
cy
*
sz
);
temp
[
2
]
=
-
cx
*
sy
;
temp
[
4
]
=
-
cx
*
sz
;
temp
[
5
]
=
cx
*
cz
;
temp
[
6
]
=
sx
;
temp
[
8
]
=
(
cz
*
sy
)
+
(
cy
*
sx
*
sz
);
temp
[
9
]
=
(
-
cy
*
cz
*
sx
)
+
(
sy
*
sz
);
temp
[
10
]
=
cx
*
cy
;
multiply_matrix
(
matrix
,
matrix
,
temp
);
}
static
int
view_set_ortho
(
float
result
[
16
],
const
float
left
,
const
float
right
,
const
float
bottom
,
const
float
top
,
const
float
near_
,
const
float
far_
)
{
if
((
right
-
left
)
==
0.0f
||
(
top
-
bottom
)
==
0.0f
||
(
far_
-
near_
)
==
0.0f
)
return
0
;
result
[
0
]
=
2.0f
/
(
right
-
left
);
result
[
1
]
=
0.0f
;
result
[
2
]
=
0.0f
;
result
[
3
]
=
0.0f
;
result
[
4
]
=
0.0f
;
result
[
5
]
=
2.0f
/
(
top
-
bottom
);
result
[
6
]
=
0.0f
;
result
[
7
]
=
0.0f
;
result
[
8
]
=
0.0f
;
result
[
9
]
=
0.0f
;
result
[
10
]
=
-
2.0f
/
(
far_
-
near_
);
result
[
11
]
=
0.0f
;
result
[
12
]
=
-
(
right
+
left
)
/
(
right
-
left
);
result
[
13
]
=
-
(
top
+
bottom
)
/
(
top
-
bottom
);
result
[
14
]
=
-
(
far_
+
near_
)
/
(
far_
-
near_
);
result
[
15
]
=
1.0f
;
return
1
;
}
static
void
init_shaders
(
GLData
*
gl_data
)
{
Evas_GL_API
*
gl
=
gl_data
->
glapi
;
const
char
*
p
;
p
=
vertex_shader
;
gl_data
->
vtx_shader
=
gl
->
glCreateShader
(
GL_VERTEX_SHADER
);
gl
->
glShaderSource
(
gl_data
->
vtx_shader
,
1
,
&
p
,
NULL
);
gl
->
glCompileShader
(
gl_data
->
vtx_shader
);
p
=
fragment_shader
;
gl_data
->
fgmt_shader
=
gl
->
glCreateShader
(
GL_FRAGMENT_SHADER
);
gl
->
glShaderSource
(
gl_data
->
fgmt_shader
,
1
,
&
p
,
NULL
);
gl
->
glCompileShader
(
gl_data
->
fgmt_shader
);
gl_data
->
program
=
gl
->
glCreateProgram
();
gl
->
glAttachShader
(
gl_data
->
program
,
gl_data
->
vtx_shader
);
gl
->
glAttachShader
(
gl_data
->
program
,
gl_data
->
fgmt_shader
);
gl
->
glBindAttribLocation
(
gl_data
->
program
,
0
,
"vPosition"
);
gl
->
glBindAttribLocation
(
gl_data
->
program
,
1
,
"inColor"
);
gl
->
glLinkProgram
(
gl_data
->
program
);
gl
->
glUseProgram
(
gl_data
->
program
);
gl
->
glEnable
(
GL_DEPTH_TEST
);
}
static
void
img_pixel_cb
(
void
*
data
,
Evas_Object
*
obj
)
{
//Define the model view projection matrix
float
model
[
16
],
mvp
[
16
];
GLData
*
gl_data
=
data
;
Evas_GL_API
*
glapi
=
gl_data
->
glapi
;
Evas_Coord
w
,
h
;
evas_object_image_size_get
(
obj
,
&
w
,
&
h
);
//Set up the context and surface as the current one
evas_gl_make_current
(
gl_data
->
evasgl
,
gl_data
->
sfc
,
gl_data
->
ctx
);
//Initialize gl stuff just one time.
if
(
!
gl_data
->
initialized
)
{
float
aspect
;
init_shaders
(
gl_data
);
glapi
->
glGenBuffers
(
1
,
&
gl_data
->
vbo
);
glapi
->
glBindBuffer
(
GL_ARRAY_BUFFER
,
gl_data
->
vbo
);
glapi
->
glBufferData
(
GL_ARRAY_BUFFER
,
3
*
72
*
4
,
cube_vertices
,
GL_STATIC_DRAW
);
init_matrix
(
gl_data
->
view
);
if
(
w
>
h
)
{
aspect
=
(
float
)
w
/
h
;
view_set_ortho
(
gl_data
->
view
,
-
1.0
*
aspect
,
1.0
*
aspect
,
-
1.0
,
1.0
,
-
1.0
,
1.0
);
}
else
{
aspect
=
(
float
)
h
/
w
;
view_set_ortho
(
gl_data
->
view
,
-
1.0
,
1.0
,
-
1.0
*
aspect
,
1.0
*
aspect
,
-
1.0
,
1.0
);
}
gl_data
->
initialized
=
EINA_TRUE
;
}
glapi
->
glViewport
(
0
,
0
,
w
,
h
);
glapi
->
glClearColor
(
0.0f
,
0.0f
,
0.0f
,
1.0f
);
glapi
->
glClear
(
GL_COLOR_BUFFER_BIT
|
GL_DEPTH_BUFFER_BIT
);
init_matrix
(
model
);
rotate_xyz
(
model
,
gl_data
->
xangle
,
gl_data
->
yangle
,
0.0f
);
multiply_matrix
(
mvp
,
gl_data
->
view
,
model
);
glapi
->
glUseProgram
(
gl_data
->
program
);
glapi
->
glBindBuffer
(
GL_ARRAY_BUFFER
,
gl_data
->
vbo
);
glapi
->
glVertexAttribPointer
(
0
,
3
,
GL_FLOAT
,
GL_FALSE
,
sizeof
(
float
)
*
6
,
0
);
glapi
->
glEnableVertexAttribArray
(
0
);
glapi
->
glBindBuffer
(
GL_ARRAY_BUFFER
,
gl_data
->
vbo
);
glapi
->
glVertexAttribPointer
(
1
,
3
,
GL_FLOAT
,
GL_FALSE
,
sizeof
(
float
)
*
6
,
(
void
*
)(
sizeof
(
float
)
*
3
));
glapi
->
glEnableVertexAttribArray
(
1
);
glapi
->
glUniformMatrix4fv
(
glapi
->
glGetUniformLocation
(
gl_data
->
program
,
"mvpMatrix"
),
1
,
GL_FALSE
,
mvp
);
glapi
->
glDrawArrays
(
GL_TRIANGLES
,
0
,
36
);
glapi
->
glFinish
();
}
static
void
img_del_cb
(
void
*
data
,
Evas
*
e
EINA_UNUSED
,
Evas_Object
*
obj
EINA_UNUSED
,
void
*
event_info
EINA_UNUSED
)
{
GLData
*
gl_data
=
data
;
Evas_GL_API
*
glapi
=
gl_data
->
glapi
;
//Free the gl resources when image object is deleted.
evas_gl_make_current
(
gl_data
->
evasgl
,
gl_data
->
sfc
,
gl_data
->
ctx
);
glapi
->
glDeleteShader
(
gl_data
->
vtx_shader
);
glapi
->
glDeleteShader
(
gl_data
->
fgmt_shader
);
glapi
->
glDeleteProgram
(
gl_data
->
program
);
glapi
->
glDeleteBuffers
(
1
,
&
gl_data
->
vbo
);
evas_gl_surface_destroy
(
gl_data
->
evasgl
,
gl_data
->
sfc
);
evas_gl_context_destroy
(
gl_data
->
evasgl
,
gl_data
->
ctx
);
evas_gl_free
(
gl_data
->
evasgl
);
}
static
Eina_Bool
_animator_cb
(
void
*
data
)
{
Evas_Object
*
img
=
data
;
//Animate here whenever an animation tick happens and then mark the image as
//"dirty" meaning it needs an update next time evas renders. it will call the
//pixel get callback then.
evas_object_image_pixels_dirty_set
(
img
,
EINA_TRUE
);
return
ECORE_CALLBACK_RENEW
;
}
static
void
_mouse_down_cb
(
void
*
data
,
Evas
*
e
EINA_UNUSED
,
Evas_Object
*
obj
EINA_UNUSED
,
void
*
event_info
EINA_UNUSED
)
{
GLData
*
gl_data
=
data
;
gl_data
->
mouse_down
=
EINA_TRUE
;
}
static
void
_mouse_move_cb
(
void
*
data
,
Evas
*
e
EINA_UNUSED
,
Evas_Object
*
obj
EINA_UNUSED
,
void
*
event_info
)
{
Evas_Event_Mouse_Move
*
ev
;
ev
=
(
Evas_Event_Mouse_Move
*
)
event_info
;
GLData
*
gl_data
=
data
;
float
dx
=
0
,
dy
=
0
;
evas_damage_rectangle_add
(
e
,
0
,
0
,
WIDTH
,
HEIGHT
);
if
(
gl_data
->
mouse_down
)
{
dx
=
(
ev
->
cur
.
canvas
.
x
-
ev
->
prev
.
canvas
.
x
);
dy
=
(
ev
->
cur
.
canvas
.
y
-
ev
->
prev
.
canvas
.
y
);
gl_data
->
xangle
+=
dy
;
gl_data
->
yangle
+=
dx
;
}
}
static
void
_mouse_up_cb
(
void
*
data
,
Evas
*
e
EINA_UNUSED
,
Evas_Object
*
obj
EINA_UNUSED
,
void
*
event_info
EINA_UNUSED
)
{
GLData
*
gl_data
=
data
;
gl_data
->
mouse_down
=
EINA_FALSE
;
}
static
void
_win_resize_cb
(
void
*
data
,
Evas
*
e
EINA_UNUSED
,
Evas_Object
*
obj
,
void
*
event_info
EINA_UNUSED
)
{
float
aspect
;
Evas_Coord
w
,
h
;
evas_object_geometry_get
(
obj
,
NULL
,
NULL
,
&
w
,
&
h
);
GLData
*
gl_data
=
data
;
evas_object_resize
(
gl_data
->
img
,
w
,
h
);
init_matrix
(
gl_data
->
view
);
if
(
w
>
h
)
{
aspect
=
(
float
)
w
/
h
;
view_set_ortho
(
gl_data
->
view
,
(
-
1.0
*
aspect
),
(
1.0
*
aspect
),
-
1.0
,
1.0
,
-
1.0
,
1.0
);
}
else
{
aspect
=
(
float
)
h
/
w
;
view_set_ortho
(
gl_data
->
view
,
-
1.0
,
1.0
,
(
-
1.0
*
aspect
),
(
1.0
*
aspect
),
-
1.0
,
1.0
);
}
}
static
void
evas_gl_exam
(
Evas_Object
*
win
)
{
Evas_Native_Surface
ns
;
//Config for the surface for evas gl
Evas_GL_Config
*
config
=
evas_gl_config_new
();
config
->
color_format
=
EVAS_GL_RGBA_8888
;
config
->
depth_bits
=
EVAS_GL_DEPTH_BIT_24
;
//Get the window size
Evas_Coord
w
,
h
;
evas_object_geometry_get
(
win
,
NULL
,
NULL
,
&
w
,
&
h
);
//Get the evas gl handle for doing gl things
gldata
.
evasgl
=
evas_gl_new
(
evas_object_evas_get
(
win
));
gldata
.
glapi
=
evas_gl_api_get
(
gldata
.
evasgl
);
//Create a surface and context
gldata
.
sfc
=
evas_gl_surface_create
(
gldata
.
evasgl
,
config
,
w
,
h
);
gldata
.
ctx
=
evas_gl_context_create
(
gldata
.
evasgl
,
NULL
);
evas_gl_config_free
(
config
);
//Set rotation variables
gldata
.
xangle
=
45.0f
;
gldata
.
yangle
=
45.0f
;
gldata
.
mouse_down
=
EINA_FALSE
;
//Set up the image object. A filled one by default.
gldata
.
img
=
evas_object_image_filled_add
(
evas_object_evas_get
(
win
));
evas_object_event_callback_add
(
gldata
.
img
,
EVAS_CALLBACK_DEL
,
img_del_cb
,
&
gldata
);
//Set up an actual pixel size for the buffer data. It may be different to the
//output size. Any windowing system has something like this, just evas has 2
//sizes, a pixel size and the output object size.
evas_object_image_size_set
(
gldata
.
img
,
w
,
h
);
//Set up the native surface info to use the context and surface created
//above.
evas_gl_native_surface_get
(
gldata
.
evasgl
,
gldata
.
sfc
,
&
ns
);
evas_object_image_native_surface_set
(
gldata
.
img
,
&
ns
);
evas_object_image_pixels_get_callback_set
(
gldata
.
img
,
img_pixel_cb
,
&
gldata
);
evas_object_resize
(
gldata
.
img
,
w
,
h
);
evas_object_show
(
gldata
.
img
);
evas_object_image_pixels_dirty_set
(
gldata
.
img
,
EINA_TRUE
);
//Add Mouse Event Callbacks
evas_object_event_callback_add
(
gldata
.
img
,
EVAS_CALLBACK_MOUSE_DOWN
,
_mouse_down_cb
,
&
gldata
);
evas_object_event_callback_add
(
gldata
.
img
,
EVAS_CALLBACK_MOUSE_UP
,
_mouse_up_cb
,
&
gldata
);
evas_object_event_callback_add
(
gldata
.
img
,
EVAS_CALLBACK_MOUSE_MOVE
,
_mouse_move_cb
,
&
gldata
);
//Add Window Resize Event Callback
evas_object_event_callback_add
(
win
,
EVAS_CALLBACK_RESIZE
,
_win_resize_cb
,
&
gldata
);
//ecore_animator_add(_animator_cb, gldata.img);
}
static
void
_on_delete_cb
(
Ecore_Evas
*
ee
EINA_UNUSED
)
{
ecore_main_loop_quit
();
}
static
void
_on_canvas_resize_cb
(
Ecore_Evas
*
ee
)
{
int
w
,
h
;
ecore_evas_geometry_get
(
ee
,
NULL
,
NULL
,
&
w
,
&
h
);
evas_object_resize
(
gldata
.
win
,
w
,
h
);
}
static
Eina_Bool
breakshit2
(
void
*
data
)
{
evas_object_del
(
data
);
return
EINA_FALSE
;
}
static
Eina_Bool
breakshit
()
{
Evas_Native_Surface
ns
;
Evas_Object
*
img
=
evas_object_image_filled_add
(
evas_object_evas_get
(
gldata
.
win
));
evas_object_image_size_set
(
img
,
WIDTH
,
HEIGHT
);
evas_object_resize
(
img
,
WIDTH
/
2
,
HEIGHT
/
2
);
evas_object_show
(
img
);
evas_gl_native_surface_get
(
gldata
.
evasgl
,
gldata
.
sfc
,
&
ns
);
evas_object_image_native_surface_set
(
img
,
&
ns
);
evas_object_image_pixels_dirty_set
(
img
,
1
);
ecore_timer_add
(
0.05
,
breakshit2
,
img
);
return
EINA_FALSE
;
}
int
main
(
void
)
{
if
(
!
ecore_evas_init
())
return
0
;
Ecore_Evas
*
ecore_evas
=
ecore_evas_new
(
"opengl_x11"
,
0
,
0
,
WIDTH
,
HEIGHT
,
NULL
);
if
(
!
ecore_evas
)
return
0
;
ecore_evas_callback_delete_request_set
(
ecore_evas
,
_on_delete_cb
);
ecore_evas_callback_resize_set
(
ecore_evas
,
_on_canvas_resize_cb
);
ecore_evas_show
(
ecore_evas
);
Evas_Object
*
evas
=
ecore_evas_get
(
ecore_evas
);
gldata
.
win
=
evas_object_rectangle_add
(
evas
);
evas_object_color_set
(
gldata
.
win
,
255
,
255
,
255
,
255
);
evas_object_resize
(
gldata
.
win
,
WIDTH
,
HEIGHT
);
evas_object_show
(
gldata
.
win
);
evas_gl_exam
(
gldata
.
win
);
ecore_timer_add
(
0.1
,
breakshit
,
NULL
);
ecore_main_loop_begin
();
ecore_evas_free
(
ecore_evas
);
ecore_evas_shutdown
();
return
0
;
}
zmike
created this paste.
May 31 2018, 4:13 AM
zmike
created this object with visibility "Public (No Login Required)".
Log In to Comment