2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
22 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_OPENGL_EGL
26 #include <wayland-extension/tizen-remote-surface-client-protocol.h>
27 #include <wayland-tbm-client.h>
31 #include "SDL_timer.h"
33 #include "../SDL_egl_c.h"
35 #include "SDL_tizenindicator.h"
36 #include "SDL_tizenwindow.h"
39 #include "SDL_opengl.h"
40 #endif /* SDL_VIDEO_OPENGL */
42 #if SDL_VIDEO_OPENGL_ES
43 #include "SDL_opengles.h"
44 #endif /* SDL_VIDEO_OPENGL_ES */
46 /* GL and GLES2 headers conflict on Linux 32 bits */
47 #if SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL
48 #include "SDL_opengles2.h"
49 #endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
51 /* EGL implementation of SDL OpenGL ES support */
52 typedef struct GLES2_Context
54 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
55 #include "../../render/opengles2/SDL_gles2funcs.h"
59 static int LoadContext(GLES2_Context * data)
61 #define SDL_PROC(ret,func,params) \
63 data->func = SDL_GL_GetProcAddress(#func); \
64 if ( ! data->func ) { \
65 return SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
69 #include "../../render/opengles2/SDL_gles2funcs.h"
75 #define IINDICATOR_HEIGHT 52
83 GLfloat vVertices[12]={
92 GLfloat vCoord[12] = {
101 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = NULL;
102 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = NULL;
103 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = NULL;
105 SharedIndicatorInfo shared_info;
107 GLuint indicator_vbo, indicator_ibo;
109 GLuint programObject;
113 Eina_Bool _tizen_timer_callback_indicator(void *data)
115 SDL_VideoDevice *_this = SDL_GetVideoDevice();
117 Tizen_DrawIndicator(_this->windows);
118 SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) _this->windows->driverdata)->egl_surface);
120 return ECORE_CALLBACK_RENEW;
124 Tizen_indicator_event_filter()
126 SDL_Window *window = SDL_GetVideoDevice()->windows;
127 SDL_WindowData *wind = window->driverdata;
129 if(wind->indicator_show && wind->indicator_timer == NULL)
131 wind->indicator_timer = ecore_timer_add(0.02, _tizen_timer_callback_indicator, NULL);
133 else if(!wind->indicator_show && wind->indicator_timer != NULL)
135 ecore_timer_del(wind ->indicator_timer);
136 wind->indicator_timer = NULL;
142 static GLuint LoadShader(GLES2_Context* Mainctx, const char *shaderSrc, GLenum type)
147 shader = Mainctx->glCreateShader(type);
148 SDL_Log("shader == %d", shader);
151 Mainctx->glShaderSource(shader, 1, &shaderSrc, NULL);
152 Mainctx->glCompileShader(shader);
153 Mainctx->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
157 Mainctx->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
160 char* infoLog = (char*)(malloc(sizeof(char) * infoLen));
161 Mainctx->glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
162 SDL_Log("Error compiling shader: %s", infoLog );
165 Mainctx->glDeleteShader(shader);
172 extern void ModelMatrixLoadIdentity(ModelMatrix* matrix)
174 matrix->m[0][0] = 1.0f;
175 matrix->m[0][1] = 0.0f;
176 matrix->m[0][2] = 0.0f;
177 matrix->m[0][3] = 0.0f;
179 matrix->m[1][0] = 0.0f;
180 matrix->m[1][1] = 1.0f;
181 matrix->m[1][2] = 0.0f;
182 matrix->m[1][3] = 0.0f;
184 matrix->m[2][0] = 0.0f;
185 matrix->m[2][1] = 0.0f;
186 matrix->m[2][2] = 1.0f;
187 matrix->m[2][3] = 0.0f;
189 matrix->m[3][0] = 0.0f;
190 matrix->m[3][1] = 0.0f;
191 matrix->m[3][2] = 0.0f;
192 matrix->m[3][3] = 1.0f;
196 static void ModelMatrixTranslate(ModelMatrix* matrix, GLfloat x, GLfloat y, GLfloat z)
198 matrix->m[3][0] += (matrix->m[0][0] * x + matrix->m[1][0] * y + matrix->m[2][0] * z);
199 matrix->m[3][1] += (matrix->m[0][1] * x + matrix->m[1][1] * y + matrix->m[2][1] * z);
200 matrix->m[3][2] += (matrix->m[0][2] * x + matrix->m[1][2] * y + matrix->m[2][2] * z);
201 matrix->m[3][3] += (matrix->m[0][3] * x + matrix->m[1][3] * y + matrix->m[2][3] * z);
205 void ModelMatrixTranslateInit(SDL_Window *window, int rot)
212 GLfloat ratio = 1 - (GLfloat)(IINDICATOR_HEIGHT*2) / window->h;
213 vVertices[3] = vVertices[5] = vVertices[11] = ratio;
216 void ModelMatrixMultiply(ModelMatrix *lhs, ModelMatrix *rhs, ModelMatrix *r)
221 for (i = 0; i < 4; i++) {
222 for (j = 0; j < 4; j++) {
225 for (k = 0; k < 4; k++) {
226 tmp[j][i] += lhs->m[k][i] * rhs->m[j][k];
230 for (i = 0; i < 4; i++) {
231 for (j=0; j<4; j++) {
232 r->m[i][j] = tmp[i][j];
237 void rotate_indicator(ModelMatrix* matrix, const float anglex, const float angley, const float anglez)
239 const float pi = 3.141592f;
240 ModelMatrix* temp = (ModelMatrix*)malloc(sizeof(ModelMatrix));
241 float rz = 2.0f * pi * anglez / 360.0f;
242 float rx = 2.0f * pi * anglex / 360.0f;
243 float ry = 2.0f * pi * angley / 360.0f;
244 float sy = SDL_sinf(ry);
245 float cy = SDL_cosf(ry);
246 float sx = SDL_sinf(rx);
247 float cx = SDL_cosf(rx);
248 float sz = SDL_sinf(rz);
249 float cz = SDL_cosf(rz);
251 ModelMatrixLoadIdentity(temp);
253 temp->m[0][0] = cy * cz - sx * sy * sz;
254 temp->m[0][1] = cz * sx * sy + cy * sz;
255 temp->m[0][2] = -cx * sy;
256 temp->m[1][0] = -cx * sz;
257 temp->m[1][1] = cx * cz;
260 temp->m[2][0] = cz * sy + cy * sx * sz;
261 temp->m[2][1] = -cy * cz * sx + sy * sz;
262 temp->m[2][2] = cx * cy;
264 ModelMatrixMultiply(matrix, temp, matrix);
268 void Tizen_UploadIndicatorImage(int idx)
270 if(!shared_info.fileInfo[idx].sharedFile
271 || shared_info.fileInfo[idx].ImageWidth == 0
272 || shared_info.fileInfo[idx].ImageHeight == 0)
275 GLES2_Context Mainctx;
276 LoadContext(&Mainctx);
278 Mainctx.glActiveTexture(GL_TEXTURE0);
280 Mainctx.glBindTexture(GL_TEXTURE_2D, textureID);
281 Mainctx.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shared_info.fileInfo[idx].ImageWidth, shared_info.fileInfo[idx].ImageHeight,
282 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*)(shared_info.fileInfo[idx].sharedFile->address));
285 SDL_bool Tizen_isTouchIndicator(SDL_Window *window, int rot, int x, int y)
287 if((window->flags & SDL_WINDOW_FULLSCREEN) || (window->flags & SDL_WINDOW_BORDERLESS))
290 if(x > window->x && x < window->x + window->w && y > window->y && y < window->y + IINDICATOR_HEIGHT)
296 int Tizen_Indicator_GLES_Init(SDL_Window* window)
298 SDL_WindowData *wind = window->driverdata;
300 int screen_w, screen_h;
301 ecore_wl_screen_size_get(&screen_w, &screen_h);
303 if(window->w < screen_w || window->h < screen_h)
306 ecore_wl_indicator_visible_type_set(wind->window, ECORE_WL_INDICATOR_VISIBLE_TYPE_SHOWN);
307 ecore_wl_window_indicator_opacity_set(wind->window, ECORE_WL_INDICATOR_OPAQUE);
308 ecore_wl_window_indicator_state_set(wind->window, ECORE_WL_INDICATOR_STATE_ON);
310 Ecore_Ipc_Server* IpcServer = serverConnection("elm_indicator", &shared_info);
313 SDL_Log("Fail to connect elm_indicator!\n");
317 GLchar vShaderStr[] =
318 "attribute vec4 vVertices;\n"
319 "attribute vec2 vCoord;\n"
320 "uniform mat4 modelMatrix;\n"
321 "varying vec2 Coord;\n"
324 " gl_Position = modelMatrix * vVertices;\n"
328 GLchar fShaderStr[] =
329 "precision mediump float;\n"
330 "varying vec2 Coord;\n"
331 "uniform sampler2D s_texture;\n"
334 " gl_FragColor = texture2D(s_texture,Coord);\n"
338 GLuint fragmentShader;
342 GLES2_Context Mainctx;
343 LoadContext(&Mainctx);
345 vertexShader = LoadShader(&Mainctx, vShaderStr, GL_VERTEX_SHADER);
346 fragmentShader = LoadShader(&Mainctx, fShaderStr, GL_FRAGMENT_SHADER);
347 SDL_Log("The vertex shader is %d", vertexShader);
348 SDL_Log("The fragment shader is %d", fragmentShader);
350 programObject = Mainctx.glCreateProgram();
351 if(programObject == 0)
354 Mainctx.glUseProgram(programObject);
356 Mainctx.glAttachShader(programObject, vertexShader);
357 Mainctx.glAttachShader(programObject, fragmentShader);
359 Mainctx.glLinkProgram(programObject);
360 Mainctx.glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
365 Mainctx.glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
368 char* infoLog = (char*)(malloc(sizeof(char) * infoLen));
369 Mainctx.glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
370 SDL_Log("Error linking program: %s", infoLog);
373 Mainctx.glDeleteProgram(programObject);
377 Mainctx.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
378 Mainctx.glEnable(GL_DEPTH_TEST);
380 vIndex = Mainctx.glGetAttribLocation(programObject, "vVertices");
381 cIndex = Mainctx.glGetAttribLocation(programObject, "vCoord");
383 Mainctx.glBindAttribLocation(programObject, vIndex, "vVertices");
384 Mainctx.glBindAttribLocation(programObject, cIndex, "vCoord");
386 ModelMatrixLoadIdentity(&mMatrix);
388 Mainctx.glGenTextures(1, &textureID);
389 Mainctx.glActiveTexture(GL_TEXTURE0);
390 Mainctx.glBindTexture(GL_TEXTURE_2D, textureID);
392 Mainctx.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
393 Mainctx.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
394 Mainctx.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
395 Mainctx.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
397 wind->indicator_show = SDL_TRUE;
398 wind->last_indicator_showtime = SDL_GetTicks();
400 ecore_main_loop_iterate();
401 Tizen_IndicatorProcessEvent(window, wind->rotation);
406 void Tizen_DrawIndicator(SDL_Window *window)
408 SDL_WindowData* wdata = (SDL_WindowData*)window->driverdata;
409 if (wdata->received_rotation == 1) {
410 ecore_wl_window_rotation_change_done_send(wdata->window);
411 wdata->received_rotation = 0;
413 if(!(window->flags & SDL_WINDOW_FULLSCREEN) && !(window->flags & SDL_WINDOW_BORDERLESS) && wdata->indicator_show)
415 if(wdata->last_indicator_showtime + 3000 < SDL_GetTicks())
419 vVertices[i] += 0.02;
421 if(wdata->last_indicator_showtime + 3500 < SDL_GetTicks())
423 wdata->indicator_show = SDL_FALSE;
425 GLES2_Context Mainctx;
426 LoadContext(&Mainctx);
427 Mainctx.glViewport(0, 0, window->w, window->h);
428 Mainctx.glUseProgram(programObject);
430 Mainctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
431 Mainctx.glVertexAttribPointer(vIndex, 2, GL_FLOAT, GL_FALSE, 0, vVertices);
432 Mainctx.glVertexAttribPointer(cIndex, 2, GL_FLOAT, GL_FALSE, 0, vCoord);
434 GLint uniformLocation = Mainctx.glGetUniformLocation(programObject, "modelMatrix");
435 Mainctx.glUniformMatrix4fv(uniformLocation, 1, GL_FALSE, (GLfloat *)mMatrix.m);
437 Mainctx.glEnableVertexAttribArray(vIndex);
438 Mainctx.glEnableVertexAttribArray(cIndex);
439 Tizen_UploadIndicatorImage(shared_info.cur_idx);
441 GLboolean isDepthTest = Mainctx.glIsEnabled(GL_DEPTH_TEST);
442 if(isDepthTest) Mainctx.glDisable(GL_DEPTH_TEST);
443 Mainctx.glDrawArrays(GL_TRIANGLES, 0, 6);
445 if(isDepthTest) Mainctx.glEnable(GL_DEPTH_TEST);
446 Mainctx.glDisableVertexAttribArray(vIndex);
447 Mainctx.glDisableVertexAttribArray(cIndex);
452 Tizen_IndicatorProcessEvent(SDL_Window *window, int rot)
454 SDL_WindowData *wind = window->driverdata;
455 if(!(window->flags & SDL_WINDOW_FULLSCREEN) && !(window->flags & SDL_WINDOW_BORDERLESS) && wind->indicator_show)
457 GLES2_Context Mainctx;
458 LoadContext(&Mainctx);
460 GLfloat ratio = 1 - (GLfloat)(52*2) / window->h;
461 vVertices[3] = vVertices[5] = vVertices[11] = ratio;
463 Mainctx.glBindBuffer(GL_ARRAY_BUFFER, indicator_vbo);
464 Mainctx.glBufferData(GL_ARRAY_BUFFER, 12 * 4, vVertices, GL_STATIC_DRAW);
465 Mainctx.glBindBuffer(GL_ARRAY_BUFFER, indicator_ibo);
466 Mainctx.glBufferData(GL_ARRAY_BUFFER, 12 * 4, vCoord, GL_STATIC_DRAW);
468 ModelMatrixLoadIdentity(&mMatrix);
470 if (!wind->support_pre_rotation)
471 rotate_indicator(&mMatrix, 0, 0, rot);
473 wind->indicator_show = SDL_TRUE;
474 wind->last_indicator_showtime = SDL_GetTicks();
479 int Tizen_FiniIndicator()
482 for (n=0; n < SHARED_FILE_NUMBER; n++)
483 Tizen_Indicator_SharedFile_Free(&shared_info, n);
485 if(shared_info.eglImage_Indicator != NULL)
486 eglDestroyImageKHR(SDL_GetVideoDevice()->egl_data->egl_display, shared_info.eglImage_Indicator);
488 if (shared_info.tizen_rs)
489 tizen_remote_surface_destroy(shared_info.tizen_rs);
490 if (shared_info.tbm_client)
491 wayland_tbm_client_deinit(shared_info.tbm_client);
492 if (shared_info.tizen_rsm)
493 tizen_remote_surface_manager_destroy(shared_info.tizen_rsm);
495 GLES2_Context Mainctx;
496 LoadContext(&Mainctx);
497 Mainctx.glDeleteProgram(programObject);
501 SDL_bool Tizen_remote_surface_init(void)
503 Eina_Inlist *globals;
504 Ecore_Wl_Global *global;
505 struct wl_registry *registry;
506 if (!shared_info.tizen_rsm)
508 registry = ecore_wl_registry_get();
509 globals = ecore_wl_globals_get();
511 if (!registry || !globals)
513 SDL_Log( "Could not get registry(%p) or global list(%p)\n", registry, globals);
517 EINA_INLIST_FOREACH(globals, global)
519 if (!strcmp(global->interface, "tizen_remote_surface_manager"))
521 shared_info.tizen_rsm = wl_registry_bind(registry, global->id,
522 &tizen_remote_surface_manager_interface, global->version<2? global->version : 2);
523 SDL_Log("[SDL] Create tizen_rsm : %p",shared_info.tizen_rsm);
526 shared_info.tizen_rs = NULL;
528 if (!shared_info.tizen_rsm)
530 SDL_Log("Could not bind tizen_remote_surface_manager");
534 if(!shared_info.tbm_client)
536 shared_info.tbm_client = (struct wayland_tbm_client *)wayland_tbm_client_init(ecore_wl_display_get());
537 shared_info.wl_tbm = (struct wl_tbm *)wayland_tbm_client_get_wl_tbm(shared_info.tbm_client);
538 if (!shared_info.wl_tbm)
540 SDL_Log("[SDL]wl_tbm is NULL");
545 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)SDL_GetVideoDevice()->egl_data->eglGetProcAddress("eglCreateImageKHR");
546 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)SDL_GetVideoDevice()->egl_data->eglGetProcAddress("eglDestroyImageKHR");
547 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)SDL_GetVideoDevice()->egl_data->eglGetProcAddress("glEGLImageTargetTexture2DOES");
552 struct wl_buffer *pre_buffer; //pre_buffer for tizen remote surface
555 _tizen_rs_cb_buffer_update(void *data, struct tizen_remote_surface *trs, struct wl_buffer *buffer, uint32_t time)
557 tizen_remote_surface_transfer_visibility(trs, TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE);
558 tbm_surface_h tbmSurface= wl_buffer_get_user_data(buffer);
559 if(eglCreateImageKHR != NULL && glEGLImageTargetTexture2DOES != NULL && eglDestroyImageKHR != NULL)
561 SDL_VideoDevice *_this = SDL_GetVideoDevice();
563 if(shared_info.eglImage_Indicator != NULL)
564 eglDestroyImageKHR(_this->egl_data->egl_display, shared_info.eglImage_Indicator);
566 shared_info.eglImage_Indicator = eglCreateImageKHR(_this->egl_data->egl_display,
567 EGL_NO_CONTEXT, EGL_NATIVE_SURFACE_TIZEN, tbmSurface, NULL);
569 if(shared_info.eglImage_Indicator == NULL)
571 SDL_Log("[SDL] eglImage is NULL");
574 SDL_Log("[SDL] eglImage : %p", shared_info.eglImage_Indicator);
575 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, shared_info.eglImage_Indicator);
579 tbm_surface_info_s info;
580 tbm_surface_map(tbmSurface, TBM_SURF_OPTION_WRITE|TBM_SURF_OPTION_READ, &info);
582 SDL_Log("[SDL] Buffer Update %p %p (%dx%d), format:%d", buffer, tbmSurface, info.width, info.height, info.format);
583 SDL_Log("[SDL] Info size:%d, offset:%d, stride:%d", info.planes[0].size, info.planes[0].offset, info.planes[0].stride);
585 GLES2_Context Mainctx;
586 LoadContext(&Mainctx);
588 Mainctx.glActiveTexture(GL_TEXTURE0);
590 Mainctx.glBindTexture(GL_TEXTURE_2D, textureID);
591 Mainctx.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info.planes[0].stride/4, info.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned int*)info.planes[0].ptr);
593 if (tbm_surface_unmap (tbmSurface) != TBM_SURFACE_ERROR_NONE)
594 SDL_Log("Failed to unmap tbm_surface\n");
599 if (tizen_remote_surface_get_version(trs) >= TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION)
600 tizen_remote_surface_release(trs, pre_buffer);
604 if (tbm_surface_destroy (tbmSurface) != TBM_SURFACE_ERROR_NONE)
605 SDL_Log("Failed to destroy tbm_surface\n");
610 _tizen_rs_cb_missing(void *data, struct tizen_remote_surface *trs)
612 SDL_Log("Plug is missing...! ");
615 static const struct tizen_remote_surface_listener _extn_gl_plug_listener =
617 _tizen_rs_cb_buffer_update,
618 _tizen_rs_cb_missing,
621 void Tizen_remote_indicator(int res_id)
623 if(!shared_info.tizen_rs) {
624 //create tizen_remote_surface
625 shared_info.tizen_rs = tizen_remote_surface_manager_create_surface(shared_info.tizen_rsm, res_id, shared_info.wl_tbm);
626 if(!shared_info.tizen_rs)
628 SDL_Log("tizen_rs is NULL");
631 tizen_remote_surface_add_listener(shared_info.tizen_rs, &_extn_gl_plug_listener, NULL);
632 tizen_remote_surface_redirect(shared_info.tizen_rs);
635 #endif /* SDL_VIDEO_DRIVER_TIZEN && SDL_VIDEO_OPENGL_EGL */