[Title] convert sdl surface to opengl surface
authorgiwoong.kim <giwoong.kim@samsung.com>
Fri, 13 Jul 2012 05:41:33 +0000 (14:41 +0900)
committergiwoong.kim <giwoong.kim@samsung.com>
Fri, 13 Jul 2012 05:41:33 +0000 (14:41 +0900)
[Type] enhancement
[Module] Emulator / skin
[Priority] major
[Jira#] BOT-821, N_SE-1482, S1-4376
[Redmine#]
[Problem]
[Cause] anti-aliasing
[Solution] using OpenGL
[TestCase]

tizen/src/maru_sdl.c
tizen/src/skin/maruskin_operation.c

index 8a357df..39e08f7 100644 (file)
 #include "maru_finger.h"
 #include "hw/maru_pm.h"
 #include "debug_ch.h"
-//#include "SDL_opengl.h"
+#include "SDL_opengl.h"
 
 MULTI_DEBUG_CHANNEL(tizen, maru_sdl);
 
 
-// TODO : organize
+DisplaySurface* qemu_display_surface = NULL;
+
 SDL_Surface *surface_screen;
 SDL_Surface *surface_qemu;
+GLuint texture;
+
+static double current_scale_factor = 1.0;
+static double current_screen_degree = 0.0;
+static int current_screen_width;
+static int current_screen_height;
 
-static double scale_factor = 1.0;
-static double screen_degree = 0.0;
 static int sdl_initialized = 0;
+static int sdl_alteration = 0;
+static int sdl_opengl = 0; //0 : just SDL surface, 1 : using SDL with OpenGL
+
 
 #define SDL_THREAD
 
@@ -60,50 +68,225 @@ static int sdl_thread_initialized = 0;
 #define SDL_FLAGS (SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_NOFRAME)
 #define SDL_BPP 32
 
-DisplaySurface* qemu_display_surface = NULL;
 
-static void qemu_update(void)
+static void _sdl_init(void)
 {
-    int i;
-    SDL_Surface *processing_screen = NULL;
+    int w, h, temp;
 
-    if (surface_qemu != NULL) {
-        if (scale_factor != 1.0 || screen_degree != 0.0) {
+    INFO("Set up a video mode with the specified width, height and bits-per-pixel\n");
+
+    //get current setting information and calculate screen size
+    current_scale_factor = get_emul_win_scale();
+    w = current_screen_width = get_emul_lcd_width() * current_scale_factor;
+    h = current_screen_height = get_emul_lcd_height() * current_scale_factor;
+
+    short rotaton_type = get_emul_rotation();
+    if (rotaton_type == ROTATION_PORTRAIT) {
+        current_screen_degree = 0.0;
+    } else if (rotaton_type == ROTATION_LANDSCAPE) {
+        current_screen_degree = 90.0;
+        temp = w;
+        w = h;
+        h = temp;
+    } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) {
+        current_screen_degree = 180.0;
+    } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) {
+        current_screen_degree = 270.0;
+        temp = w;
+        w = h;
+        h = temp;
+    }
 
-            // workaround
-            // set color key 'magenta'
-            surface_qemu->format->colorkey = 0xFF00FF;
+    surface_screen = SDL_SetVideoMode(w, h, get_emul_sdl_bpp(), SDL_OPENGL);
+    if (surface_screen == NULL) {
+        sdl_opengl = 0;
+        INFO("No OpenGL support on this system!??\n");
+        ERR("%s\n", SDL_GetError());
 
-            //image processing
-            processing_screen = rotozoomSurface(surface_qemu, screen_degree, scale_factor, 1);
-            SDL_BlitSurface(processing_screen, NULL, surface_screen, NULL);
-        } else {
-            SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL);
+        surface_screen = SDL_SetVideoMode(w, h, get_emul_sdl_bpp(), SDL_FLAGS);
+        if (surface_screen == NULL) {
+            ERR("Could not open SDL display (%dx%dx%d): %s\n", w, h, get_emul_sdl_bpp(), SDL_GetError());
+            return;
         }
+    } else {
+        sdl_opengl = 1;
+        INFO("OpenGL is supported on this system.\n");
+    }
+
+    if (sdl_opengl == 1) {
+        /* Set the OpenGL state */
+        glClearColor(0, 0, 0, 0);
+        glViewport(0, 0, w, h);
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        glOrtho(0, w, h, 0, -1, 1);
+        glMatrixMode(GL_MODELVIEW);
+
+        glGenTextures(1, &texture);
+        glBindTexture(GL_TEXTURE_2D, texture);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    }
+}
+
+static int point_degree = 0;
+static void draw_outline_circle(int cx, int cy, int r, int num_segments)
+{
+    int ii;
+    float theta = 2 * 3.1415926 / (num_segments);
+    float c = cosf(theta);//precalculate the sine and cosine
+    float s = sinf(theta);
+    float t;
+
+    float x = r;//we start at angle = 0
+    float y = 0;
+
+    glEnable(GL_LINE_STIPPLE);
+    glColor3f(0.9, 0.9, 0.9);
+    glLineStipple(1, 0xcccc);
+    glLineWidth(3.f);
+    glLoadIdentity();
+
+    glTranslatef(cx, cy, 0);
+    glRotated(point_degree++ % 360, 0, 0, 1);
+
+    glBegin(GL_LINE_LOOP);
+    for(ii = 0; ii < num_segments; ii++) {
+        glVertex2f(x, y); //output vertex
+
+        //apply the rotation matrix
+        t = x;
+        x = c * x - s * y;
+        y = s * t + c * y;
+    }
+    glEnd();
+
+    glDisable(GL_LINE_STIPPLE);
+}
+
+static void draw_fill_circle(int cx, int cy, int r)
+{
+    glEnable(GL_POINT_SMOOTH);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glColor4f(0.1, 0.1, 0.1, 0.6);
+    glPointSize(r - 2);
+    glLoadIdentity();
+
+    glBegin(GL_POINTS);
+        glVertex2f(cx, cy);
+    glEnd();
+
+    glDisable(GL_POINT_SMOOTH);
+    glDisable(GL_BLEND);
+}
+
+static void qemu_update(void)
+{
+    if (sdl_alteration == 1) {
+        sdl_alteration = 0;
+        _sdl_init();
+        return;
     }
 
-    /* draw multi-touch finger points */
-    MultiTouchState *mts = get_emul_multi_touch_state();
-    if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) {
-        FingerPoint *finger = NULL;
-        int finger_point_size_half = mts->finger_point_size / 2;
-        SDL_Rect rect;
-
-        for (i = 0; i < mts->finger_cnt; i++) {
-            finger = get_finger_point_from_slot(i);
-            if (finger != NULL && finger->id != 0) {
-                rect.x = finger->origin_x - finger_point_size_half;
-                rect.y = finger->origin_y - finger_point_size_half;
-                rect.w = rect.h = mts->finger_point_size;
-
-                SDL_BlitSurface((SDL_Surface *)mts->finger_point_surface, NULL, surface_screen, &rect);
+    if (surface_qemu != NULL) {
+        int i;
+
+        if (sdl_opengl == 1)
+        { //gl surface
+            glEnable(GL_TEXTURE_2D); //enable server-side GL capabilities
+            glColor3f(1.0, 1.0, 1.0);
+            glTexImage2D(GL_TEXTURE_2D,
+                0, 3, surface_qemu->w, surface_qemu->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, surface_qemu->pixels);
+            glBindTexture(GL_TEXTURE_2D, texture);
+
+            glClear(GL_COLOR_BUFFER_BIT);
+            glLoadIdentity();
+
+            /* rotation */
+            if (current_screen_degree == 270.0) { //reverse landscape
+                glRotated(90, 0, 0, 1);
+                glTranslatef(0, -current_screen_height, 0);
+            } else if (current_screen_degree == 180.0) { //reverse portrait
+                glRotated(180, 0, 0, 1);
+                glTranslatef(-current_screen_width, -current_screen_height, 0);
+            } else if (current_screen_degree == 90.0) { //landscape
+                glRotated(270, 0, 0, 1);
+                glTranslatef(-current_screen_width, 0, 0);
+            }
+
+            glBegin(GL_QUADS);
+                glTexCoord2i(0, 0);
+                glVertex3f(0, 0, 0);
+                glTexCoord2i(1, 0);
+                glVertex3f(current_screen_width, 0, 0);
+                glTexCoord2i(1, 1);
+                glVertex3f(current_screen_width, current_screen_height, 0);
+                glTexCoord2i(0, 1);
+                glVertex3f(0, current_screen_height, 0);
+            glEnd();
+
+            glDisable(GL_TEXTURE_2D);
+
+            /* draw multi-touch finger points */
+            MultiTouchState *mts = get_emul_multi_touch_state();
+            if (mts->multitouch_enable != 0) {
+                FingerPoint *finger = NULL;
+                int finger_point_size_half = mts->finger_point_size / 2;
+
+                for (i = 0; i < mts->finger_cnt; i++) {
+                    finger = get_finger_point_from_slot(i);
+                    if (finger != NULL && finger->id != 0) {
+                        draw_outline_circle(finger->origin_x, finger->origin_y, finger_point_size_half, 10); //TODO: optimize
+                        draw_fill_circle(finger->origin_x, finger->origin_y, mts->finger_point_size);
+                    }
+                }
+            } //end  of draw multi-touch
+
+            glFlush();
+
+            SDL_GL_SwapBuffers();
+        }
+        else
+        { //sdl surface
+            SDL_Surface *processing_screen = NULL;
+
+            if (current_scale_factor != 1.0 || current_screen_degree != 0.0) {
+                // workaround
+                // set color key 'magenta'
+                surface_qemu->format->colorkey = 0xFF00FF;
+
+                //image processing
+                processing_screen = rotozoomSurface(surface_qemu, current_screen_degree, current_scale_factor, 1);
+                SDL_BlitSurface(processing_screen, NULL, surface_screen, NULL);
+            } else {
+                SDL_BlitSurface(surface_qemu, NULL, surface_screen, NULL);
             }
+
+            SDL_FreeSurface(processing_screen);
+
+            /* draw multi-touch finger points */
+            MultiTouchState *mts = get_emul_multi_touch_state();
+            if (mts->multitouch_enable != 0 && mts->finger_point_surface != NULL) {
+                FingerPoint *finger = NULL;
+                int finger_point_size_half = mts->finger_point_size / 2;
+                SDL_Rect rect;
+
+                for (i = 0; i < mts->finger_cnt; i++) {
+                    finger = get_finger_point_from_slot(i);
+                    if (finger != NULL && finger->id != 0) {
+                        rect.x = finger->origin_x - finger_point_size_half;
+                        rect.y = finger->origin_y - finger_point_size_half;
+                        rect.w = rect.h = mts->finger_point_size;
+
+                        SDL_BlitSurface((SDL_Surface *)mts->finger_point_surface, NULL, surface_screen, &rect);
+                    }
+                }
+            } //end  of draw multi-touch
         }
     }
 
     SDL_UpdateRect(surface_screen, 0, 0, 0, 0);
-
-    SDL_FreeSurface(processing_screen);
 }
 
 
@@ -162,7 +345,7 @@ static void qemu_ds_resize(DisplayState *ds)
 #endif
 
     if (surface_qemu == NULL) {
-        ERR( "Unable to set the RGBSurface: %s", SDL_GetError() );
+        ERR("Unable to set the RGBSurface: %s\n", SDL_GetError());
         return;
     }
 
@@ -181,8 +364,8 @@ static int maru_sdl_poll_event(SDL_Event *ev)
     return ret;
 }
 
-static void put_hardkey_code( SDL_UserEvent event ) {
-
+static void put_hardkey_code( SDL_UserEvent event )
+{
     // use pointer as integer
     int event_type = (int) event.data1;
     int keycode = (int) event.data2;
@@ -200,13 +383,13 @@ static void put_hardkey_code( SDL_UserEvent event ) {
         }
 
     } else {
-        ERR( "Unknown hardkey event type.[event_type:%d]", event_type );
+        ERR( "Unknown hardkey event type.[event_type:%d]\n", event_type );
     }
 
 }
 
-static void handle_sdl_user_event ( SDL_UserEvent event ) {
-
+static void handle_sdl_user_event ( SDL_UserEvent event )
+{
     int code = event.code;
 
     switch ( code ) {
@@ -256,7 +439,7 @@ static void qemu_ds_refresh(DisplayState *ds)
 
 void maruskin_display_init(DisplayState *ds)
 {
-    INFO( "qemu display initialization\n");
+    INFO("qemu display initialization\n");
 
     /*  graphics context information */
     DisplayChangeListener *dcl;
@@ -271,18 +454,19 @@ void maruskin_display_init(DisplayState *ds)
 
 void maruskin_sdl_init(uint64 swt_handle, int lcd_size_width, int lcd_size_height, bool is_resize)
 {
-    int w, h, temp;
     gchar SDL_windowhack[32];
     SDL_SysWMinfo info;
     long window_id = swt_handle;
 
+    INFO("maru sdl initialization = %d\n", is_resize);
+
     if (is_resize == FALSE) {
         sprintf(SDL_windowhack, "%ld", window_id);
         g_setenv("SDL_WINDOWID", SDL_windowhack, 1);
         INFO("register SDL environment variable. (SDL_WINDOWID = %s)\n", SDL_windowhack);
 
         if (SDL_Init(SDL_INIT_VIDEO) < 0 ) {
-            ERR( "unable to init SDL: %s", SDL_GetError() );
+            ERR("unable to init SDL: %s\n", SDL_GetError());
             exit(1);
         }
 
@@ -290,55 +474,31 @@ void maruskin_sdl_init(uint64 swt_handle, int lcd_size_width, int lcd_size_heigh
         set_emul_sdl_bpp(SDL_BPP);
     }
 
-    //get current setting information and calculate screen size
-    scale_factor = get_emul_win_scale();
-    w = lcd_size_width * scale_factor;
-    h = lcd_size_height * scale_factor;
+    if (sdl_initialized == 0) {
+        sdl_initialized = 1;
 
-    short rotaton_type = get_emul_rotation();
-    if (rotaton_type == ROTATION_PORTRAIT) {
-        screen_degree = 0.0;
-    } else if (rotaton_type == ROTATION_LANDSCAPE) {
-        screen_degree = 90.0;
-        temp = w;
-        w = h;
-        h = temp;
-    } else if (rotaton_type == ROTATION_REVERSE_PORTRAIT) {
-        screen_degree = 180.0;
-    } else if (rotaton_type == ROTATION_REVERSE_LANDSCAPE) {
-        screen_degree = 270.0;
-        temp = w;
-        w = h;
-        h = temp;
-    }
+        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+        init_multi_touch_state();
 
-    INFO( "maru sdl initialization\n");
-    surface_screen = SDL_SetVideoMode(w, h, get_emul_sdl_bpp(), SDL_FLAGS);
-    if (surface_screen == NULL) {
-        ERR("Could not open SDL display (%dx%dx%d): %s\n", w, h, get_emul_sdl_bpp(), SDL_GetError());
+#ifndef _WIN32
+        SDL_VERSION(&info.version);
+        SDL_GetWMInfo(&info);
+#endif
     }
 
+    sdl_alteration = 1;
+
 #ifdef SDL_THREAD
     if (sdl_thread_initialized == 0) {
         sdl_thread_initialized = 1;
         pthread_t thread_id;
-        INFO( "sdl update thread create\n");
+        INFO("sdl update thread create\n");
         if (pthread_create(&thread_id, NULL, run_qemu_update, NULL) != 0) {
-            ERR( "pthread_create fail\n");
+            ERR("pthread_create fail\n");
             return;
         }
     }
 #endif
-
-#ifndef _WIN32
-    SDL_VERSION(&info.version);
-    SDL_GetWMInfo(&info);
-#endif
-
-    if (sdl_initialized == 0) {
-        sdl_initialized = 1;
-        init_multi_touch_state();
-    }
 }
 
 void maruskin_sdl_resize(void)
@@ -356,3 +516,4 @@ void maruskin_sdl_resize(void)
 DisplaySurface* get_qemu_display_surface( void ) {
     return qemu_display_surface;
 }
+
index a7d204b..3da625a 100644 (file)
@@ -191,7 +191,7 @@ void do_hardkey_event( int event_type, int keycode )
 
 void do_scale_event( double scale_factor )
 {
-    INFO( "do_scale_event scale_factor:%lf", scale_factor);
+    INFO("do_scale_event scale_factor:%lf\n", scale_factor);
 
     set_emul_win_scale(scale_factor);