Source/WebKit/efl: [EFL] Add new pre-rendering code.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jan 2012 11:25:24 +0000 (11:25 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 6 Jan 2012 11:25:24 +0000 (11:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=73430

Patch by JungJik Lee <jungjik.lee@samsung.com> on 2012-01-06
Reviewed by Zoltan Herczeg.

Add new pre-rendering code to pre-render the view area more efficiently.
At first find centered view position where backing store starts to queuing the render request from.
And append the request into the tiled backing store in spiral order.

* ewk/ewk_private.h:
* ewk/ewk_tiled_backing_store.cpp:
(ewk_tiled_backing_store_pre_render_tile_add):
(ewk_tiled_backing_store_pre_render_spiral_queue):
* ewk/ewk_tiled_backing_store.h:
* ewk/ewk_view.cpp:
(_ewk_view_smart_pre_render_start):
(ewk_view_base_smart_set):
(ewk_view_pre_render_start):
* ewk/ewk_view.h:
* ewk/ewk_view_tiled.cpp:
(_ewk_view_tiled_rect_collision_check):
(_ewk_view_tiled_rect_collision_resolve):
(_ewk_view_tiled_smart_pre_render_start):
(ewk_view_tiled_smart_set):

Tools: [EFL] Add pre-render handling code in EWebLauncher.
https://bugs.webkit.org/show_bug.cgi?id=73430

Patch by JungJik Lee <jungjik.lee@samsung.com> on 2012-01-06
Reviewed by Zoltan Herczeg.

Add pre-render handling code by pressing Insert key.

* EWebLauncher/main.c:
(on_key_down):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@104282 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/efl/ChangeLog
Source/WebKit/efl/ewk/ewk_private.h
Source/WebKit/efl/ewk/ewk_tiled_backing_store.cpp
Source/WebKit/efl/ewk/ewk_tiled_backing_store.h
Source/WebKit/efl/ewk/ewk_view.cpp
Source/WebKit/efl/ewk/ewk_view.h
Source/WebKit/efl/ewk/ewk_view_tiled.cpp
Tools/ChangeLog
Tools/EWebLauncher/main.c

index 6849537..ffe7a10 100644 (file)
@@ -1,3 +1,30 @@
+2012-01-06  JungJik Lee  <jungjik.lee@samsung.com>
+
+        [EFL] Add new pre-rendering code.
+        https://bugs.webkit.org/show_bug.cgi?id=73430
+
+        Reviewed by Zoltan Herczeg.
+
+        Add new pre-rendering code to pre-render the view area more efficiently.
+        At first find centered view position where backing store starts to queuing the render request from.
+        And append the request into the tiled backing store in spiral order.
+
+        * ewk/ewk_private.h:
+        * ewk/ewk_tiled_backing_store.cpp:
+        (ewk_tiled_backing_store_pre_render_tile_add):
+        (ewk_tiled_backing_store_pre_render_spiral_queue):
+        * ewk/ewk_tiled_backing_store.h:
+        * ewk/ewk_view.cpp:
+        (_ewk_view_smart_pre_render_start):
+        (ewk_view_base_smart_set):
+        (ewk_view_pre_render_start):
+        * ewk/ewk_view.h:
+        * ewk/ewk_view_tiled.cpp:
+        (_ewk_view_tiled_rect_collision_check):
+        (_ewk_view_tiled_rect_collision_resolve):
+        (_ewk_view_tiled_smart_pre_render_start):
+        (ewk_view_tiled_smart_set):
+
 2012-01-05  KwangHyuk Kim  <hyuki.kim@samsung.com>
 
         [EFL] Invalidation request for ewk_view can be discarded without rendering.
index 9ab1211..2025941 100644 (file)
@@ -45,6 +45,7 @@ extern "C" {
 
 // If defined, ewk will do type checking to ensure objects are of correct type
 #define EWK_TYPE_CHECK 1
+#define EWK_ARGB_BYTES_SIZE 4
 
 #if ENABLE(NETSCAPE_PLUGIN_API)
 #define EWK_JS_OBJECT_MAGIC 0x696969
index 25268b3..be05133 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "ewk_tiled_backing_store.h"
 
+#include "ewk_private.h"
 #include "ewk_tiled_matrix.h"
 #include "ewk_tiled_private.h"
 #include <Ecore.h>
@@ -1838,6 +1839,111 @@ void ewk_tiled_backing_store_flush(Evas_Object* ewkBackingStore)
 #endif
 }
 
+Eina_Bool ewk_tiled_backing_store_pre_render_tile_add(Evas_Object* ewkBackingStore, int column, int row, float zoom)
+{
+    PRIV_DATA_GET_OR_RETURN(ewkBackingStore, priv, false);
+
+    if (ewk_tile_matrix_tile_exact_exists(priv->model.matrix, column, row, zoom))
+        return false;
+
+    if (!_ewk_tiled_backing_store_pre_render_request_add(priv, column, row, zoom))
+        return false;
+
+    return true;
+}
+
+Eina_Bool ewk_tiled_backing_store_pre_render_spiral_queue(Evas_Object* ewkBackingStore, Eina_Rectangle* viewRect, Eina_Rectangle* renderRect, int maxMemory, float zoom)
+{
+    PRIV_DATA_GET_OR_RETURN(ewkBackingStore, priv, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(viewRect, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(renderRect, false);
+
+    const int tileWidth = priv->view.tile.width;
+    const int tileHeight = priv->view.tile.height;
+
+    Eina_Tile_Grid_Slicer viewSlicer;
+    Eina_Tile_Grid_Slicer renderSlicer;
+
+    if (!eina_tile_grid_slicer_setup(&viewSlicer,
+        viewRect->x, viewRect->y, viewRect->w, viewRect->h, tileWidth, tileHeight)) {
+        ERR("could not setup grid viewSlicer for %d,%d+%dx%d tile=%dx%d", viewRect->x, viewRect->y, viewRect->w, viewRect->h, tileWidth, tileHeight);
+        return false;
+    }
+
+    if (!eina_tile_grid_slicer_setup(&renderSlicer,
+        renderRect->x, renderRect->y, renderRect->w, renderRect->h, tileWidth, tileHeight)) {
+        ERR("could not setup grid RenderSlicer for %d,%d+%dx%d tile=%dx%d", renderRect->y, renderRect->y, renderRect->w, renderRect->h, tileWidth, tileHeight);
+        return false;
+    }
+
+    // set limits of the loop.
+    int memoryLimits = maxMemory / (EWK_ARGB_BYTES_SIZE * tileWidth * tileHeight);
+    const int maxViewSideLength = std::max(viewSlicer.col2 - viewSlicer.col1, viewSlicer.row2 - viewSlicer.row1);
+    const int maxRenderSideLength = std::max(renderSlicer.col2 - renderSlicer.col1, renderSlicer.row2 - renderSlicer.row1);
+    const int maxLoopCount = maxViewSideLength + maxRenderSideLength;
+
+    // spire starts from the center of the view area.
+    int centerColumn = (viewSlicer.col1 + viewSlicer.col2) / 2;
+    int centerRow = (viewSlicer.row1 + viewSlicer.row2) / 2;
+
+    int step = 1;
+    const int squareSide = 4;
+    for (int loop = 0; loop < maxLoopCount; loop++) {
+        for (int i = 1; i < step * squareSide + 1; i++) {
+            if (memoryLimits <= 0)
+                goto memoryLimitsReached;
+            /*
+            this code means the loop runs like spiral. (i.g. left->down->right->up)
+            when it moves back to original place and then walk 1 tile left and up.
+            the loop keeps on doing this until it reaches max memory to draw tiles.
+            e.g. )
+                         333333
+                         322223
+                         321123
+                         321123
+                         322223
+                         333333
+            */
+            if (i > 0 && i <= step)
+                centerColumn++; // move left.
+            else if (i > step && i <= step * 2)
+                centerRow++; // move down.
+            else if (i > step * 2 && i <= step * 3)
+                centerColumn--; // move right.
+            else if (i > step * 3 && i <= step * 4)
+                centerRow--; // move up.
+            else
+                ERR("ERROR : out of bounds\r\n");
+
+            // skip in view port area.
+            if (static_cast<int>(viewSlicer.col1) < centerColumn
+                && static_cast<int>(viewSlicer.col2) > centerColumn
+                && static_cast<int>(viewSlicer.row1) < centerRow
+                && static_cast<int>(viewSlicer.row2) > centerRow)
+                continue;
+
+            if (static_cast<int>(renderSlicer.col1) <= centerColumn
+                && static_cast<int>(renderSlicer.col2) >= centerColumn
+                && static_cast<int>(renderSlicer.row1) <= centerRow
+                && static_cast<int>(renderSlicer.row2) >= centerRow) {
+
+                if (!ewk_tiled_backing_store_pre_render_tile_add(ewkBackingStore, centerColumn, centerRow, zoom))
+                    continue;
+                DBG("R>[%d %d] ", centerColumn, centerRow);
+                memoryLimits--;
+            }
+        }
+        centerRow--;
+        centerColumn--;
+        step = step + 2;
+    }
+
+memoryLimitsReached:
+    _ewk_tiled_backing_store_item_process_idler_start(priv);
+
+    return true;
+}
+
 Eina_Bool ewk_tiled_backing_store_pre_render_region(Evas_Object* ewkBackingStore, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height, float zoom)
 {
     PRIV_DATA_GET_OR_RETURN(ewkBackingStore, priv, false);
index e911947..44740cb 100644 (file)
@@ -112,6 +112,7 @@ void ewk_tiled_backing_store_tile_unused_cache_set(Evas_Object* o, Ewk_Tile_Unus
 
 Eina_Bool ewk_tiled_backing_store_pre_render_region(Evas_Object* o, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom);
 Eina_Bool ewk_tiled_backing_store_pre_render_relative_radius(Evas_Object* o, unsigned int n, float zoom);
+Eina_Bool ewk_tiled_backing_store_pre_render_spiral_queue(Evas_Object* o, Eina_Rectangle* view_rect, Eina_Rectangle* render_rect, int max_memory, float zoom);
 void ewk_tiled_backing_store_pre_render_cancel(Evas_Object* o);
 
 Eina_Bool ewk_tiled_backing_store_disable_render(Evas_Object* o);
index dd0d89b..53a2d0a 100644 (file)
@@ -1005,6 +1005,12 @@ static Eina_Bool _ewk_view_smart_pre_render_relative_radius(Ewk_View_Smart_Data*
     return false;
 }
 
+static Eina_Bool _ewk_view_smart_pre_render_start(Ewk_View_Smart_Data* smartData)
+{
+    WRN("not supported by engine. smartData=%p", smartData);
+    return false;
+}
+
 static void _ewk_view_smart_pre_render_cancel(Ewk_View_Smart_Data* smartData)
 {
     WRN("not supported by engine. smartData=%p", smartData);
@@ -1137,6 +1143,7 @@ Eina_Bool ewk_view_base_smart_set(Ewk_View_Smart_Class* api)
     api->flush = _ewk_view_smart_flush;
     api->pre_render_region = _ewk_view_smart_pre_render_region;
     api->pre_render_relative_radius = _ewk_view_smart_pre_render_relative_radius;
+    api->pre_render_start = _ewk_view_smart_pre_render_start;
     api->pre_render_cancel = _ewk_view_smart_pre_render_cancel;
     api->disable_render = _ewk_view_smart_disable_render;
     api->enable_render = _ewk_view_smart_enable_render;
@@ -1834,6 +1841,14 @@ Eina_Bool ewk_view_pre_render_relative_radius(Evas_Object* ewkView, unsigned int
     return smartData->api->pre_render_relative_radius(smartData, number, currentZoom);
 }
 
+Eina_Bool ewk_view_pre_render_start(Evas_Object* ewkView)
+{
+    EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false);
+    EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->api->pre_render_start, false);
+
+    return smartData->api->pre_render_start(smartData);
+}
+
 unsigned int ewk_view_imh_get(const Evas_Object* ewkView)
 {
     EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0);
index d1c65eb..d0be61d 100644 (file)
@@ -135,6 +135,7 @@ struct _Ewk_View_Smart_Class {
     void (*flush)(Ewk_View_Smart_Data *sd);
     Eina_Bool (*pre_render_region)(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, float zoom);
     Eina_Bool (*pre_render_relative_radius)(Ewk_View_Smart_Data *sd, unsigned int n, float zoom);
+    Eina_Bool (*pre_render_start)(Ewk_View_Smart_Data *sd);
     void (*pre_render_cancel)(Ewk_View_Smart_Data *sd);
     Eina_Bool (*disable_render)(Ewk_View_Smart_Data *sd);
     Eina_Bool (*enable_render)(Ewk_View_Smart_Data *sd);
@@ -168,7 +169,7 @@ struct _Ewk_View_Smart_Class {
  * The version you have to put into the version field
  * in the @a Ewk_View_Smart_Class structure.
  */
-#define EWK_VIEW_SMART_CLASS_VERSION 3UL
+#define EWK_VIEW_SMART_CLASS_VERSION 4UL
 
 /**
  * Initializes a whole @a Ewk_View_Smart_Class structure.
@@ -180,7 +181,7 @@ struct _Ewk_View_Smart_Class {
  * @see EWK_VIEW_SMART_CLASS_INIT_VERSION
  * @see EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION
  */
-#define EWK_VIEW_SMART_CLASS_INIT(smart_class_init) {smart_class_init, EWK_VIEW_SMART_CLASS_VERSION, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+#define EWK_VIEW_SMART_CLASS_INIT(smart_class_init) {smart_class_init, EWK_VIEW_SMART_CLASS_VERSION, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
 /**
  * Initializes to zero a whole @a Ewk_View_Smart_Class structure.
@@ -314,6 +315,10 @@ struct _Ewk_View_Smart_Data {
         Eina_Bool position:1;
         Eina_Bool frame_rect:1;
     } changed; /**< Keeps what changed since last smart_calculate. */
+    struct {
+        Evas_Coord x, y;
+        float zoom;
+    } previousView;
 };
 
 /// Defines the modes of view.
@@ -1249,6 +1254,23 @@ EAPI Eina_Bool    ewk_view_pre_render_region(Evas_Object *o, Evas_Coord x, Evas_
 EAPI Eina_Bool    ewk_view_pre_render_relative_radius(Evas_Object *o, unsigned int n);
 
 /**
+ * Asks engine to start pre-rendering.
+ *
+ * This is an alternative method to pre-render around the view area.
+ * The first step is to find the center view area where to start pre-rendering.
+ * And then from the center of the view area the backing store append the render request
+ * outward in spiral order. So that the tiles which are close to view area are displayed
+ * sooner than outside.
+ *
+ * @param o view to ask pre-render
+ *
+ * @return @c EINA_TRUE if request was accepted, @c EINA_FALSE
+ *         otherwise (errors, pre-render feature not supported, etc)
+ *
+ */
+EAPI Eina_Bool    ewk_view_pre_render_start(Evas_Object *o);
+
+/**
  * Cancels and clears previous the pre-render requests.
  *
  * @param o view to clear pre-render requests
index b8ace0f..3101c12 100644 (file)
@@ -209,6 +209,123 @@ static Eina_Bool _ewk_view_tiled_smart_pre_render_relative_radius(Ewk_View_Smart
                (smartData->backing_store, n, zoom);
 }
 
+static inline int _ewk_view_tiled_rect_collision_check(Eina_Rectangle destination, Eina_Rectangle source)
+{
+    int direction = 0;
+    if (destination.x < source.x)
+        direction = direction | (1 << 0); // 0 bit shift, left
+    if (destination.y < source.y)
+        direction = direction | (1 << 1); // 1 bit shift, top
+    if (destination.x + destination.w > source.x + source.w)
+        direction = direction | (1 << 2); // 2 bit shift, right
+    if (destination.y + destination.h > source.y + source.h)
+        direction = direction | (1 << 3); // 3 bit shift, bottom
+    DBG("check collision %d\r\n", direction);
+    return direction;
+}
+
+static inline void _ewk_view_tiled_rect_collision_resolve(int direction, Eina_Rectangle* destination, Eina_Rectangle source)
+{
+    if (direction & (1 << 0)) // 0 bit shift, left
+        destination->x = source.x;
+    if (direction & (1 << 1)) // 1 bit shift, top
+        destination->y = source.y;
+    if (direction & (1 << 2)) // 2 bit shift, right
+        destination->x = destination->x - ((destination->x + destination->w) - (source.x + source.w));
+    if (direction & (1 << 3)) // 3 bit shift, bottom
+        destination->y = destination->y - ((destination->y + destination->h) - (source.y + source.h));
+}
+
+static Eina_Bool _ewk_view_tiled_smart_pre_render_start(Ewk_View_Smart_Data* smartData)
+{
+    int contentWidth, contentHeight;
+    ewk_frame_contents_size_get(smartData->main_frame, &contentWidth, &contentHeight);
+
+    int viewX, viewY, viewWidth, viewHeight;
+    ewk_frame_visible_content_geometry_get(smartData->main_frame, false, &viewX, &viewY, &viewWidth, &viewHeight);
+
+    if (viewWidth <= 0 || viewHeight <= 0 || contentWidth <= 0 || contentHeight <= 0)
+        return false;
+
+    if (viewWidth >= contentWidth && viewHeight >= contentHeight)
+        return false;
+
+    int previousViewX, previousViewY;
+    previousViewX = smartData->previousView.x;
+    previousViewY = smartData->previousView.y;
+
+    if (previousViewX < 0 || previousViewX > contentWidth || previousViewY < 0 || previousViewY > contentHeight)
+        previousViewX = previousViewY = 0;
+
+    float currentViewZoom = ewk_view_zoom_get(smartData->self);
+
+    // pre-render works when two conditions are met.
+    // zoom has been changed.
+    // and the view has been moved more than tile size.
+    if (abs(previousViewX - viewX) < DEFAULT_TILE_W
+        && abs(previousViewY - viewY) < DEFAULT_TILE_H
+        && smartData->previousView.zoom == currentViewZoom) {
+        return false;
+    }
+
+    // store previous view position and zoom.
+    smartData->previousView.x = viewX;
+    smartData->previousView.y = viewY;
+    smartData->previousView.zoom = currentViewZoom;
+
+    // cancelling previous pre-rendering list if exists.
+    ewk_view_pre_render_cancel(smartData->self);
+
+    Ewk_Tile_Unused_Cache* tileUnusedCache = ewk_view_tiled_unused_cache_get(smartData->self);
+    int maxMemory = ewk_tile_unused_cache_max_get(tileUnusedCache);
+    if (maxMemory <= viewWidth * viewHeight * EWK_ARGB_BYTES_SIZE)
+        return false;
+
+    Eina_Rectangle viewRect = {viewX, viewY, viewWidth, viewHeight};
+    Eina_Rectangle contentRect = {0, 0, contentWidth, contentHeight};
+
+    // get a base render rect.
+    const int contentMemory = contentWidth * contentHeight * EWK_ARGB_BYTES_SIZE;
+
+    // get render rect's width and height.
+    Eina_Rectangle renderRect;
+    if (maxMemory > contentMemory)
+        renderRect = contentRect;
+    else {
+        // Make a base rectangle as big as possible with using maxMemory.
+        // and then reshape the base rectangle to fit to contents.
+        const int baseSize = static_cast<int>(sqrt(maxMemory / 4.0f));
+        const float widthRate = (viewRect.w + (DEFAULT_TILE_W * 2)) / static_cast<float>(baseSize);
+        const float heightRate = baseSize / static_cast<float>(contentHeight);
+        const float rectRate = std::max(widthRate, heightRate);
+
+        renderRect.w = static_cast<int>(baseSize * rectRate);
+        renderRect.h = static_cast<int>(baseSize / rectRate);
+        renderRect.x = viewRect.x + (viewRect.w / 2) - (renderRect.w / 2);
+        renderRect.y = viewRect.y + (viewRect.h / 2) - (renderRect.h / 2);
+
+        // reposition of renderRect, if the renderRect overlapped the content rect, this code moves the renderRect inside the content rect.
+        int collisionSide = _ewk_view_tiled_rect_collision_check(renderRect, contentRect);
+        if (collisionSide > 0)
+            _ewk_view_tiled_rect_collision_resolve(collisionSide, &renderRect, contentRect);
+
+        // check abnormal render rect
+        if (renderRect.x < 0)
+            renderRect.x = 0;
+        if (renderRect.y < 0)
+            renderRect.y = 0;
+        if (renderRect.w > contentWidth)
+            renderRect.w = contentWidth;
+        if (renderRect.h > contentHeight)
+            renderRect.h = contentHeight;
+    }
+
+    // enqueue tiles into tiled backing store in spiral order.
+    ewk_tiled_backing_store_pre_render_spiral_queue(smartData->backing_store, &viewRect, &renderRect, maxMemory, currentViewZoom);
+
+    return true;
+}
+
 static void _ewk_view_tiled_smart_pre_render_cancel(Ewk_View_Smart_Data* smartData)
 {
     ewk_tiled_backing_store_pre_render_cancel(smartData->backing_store);
@@ -248,6 +365,7 @@ Eina_Bool ewk_view_tiled_smart_set(Ewk_View_Smart_Class* api)
     api->flush = _ewk_view_tiled_smart_flush;
     api->pre_render_region = _ewk_view_tiled_smart_pre_render_region;
     api->pre_render_relative_radius = _ewk_view_tiled_smart_pre_render_relative_radius;
+    api->pre_render_start = _ewk_view_tiled_smart_pre_render_start;
     api->pre_render_cancel = _ewk_view_tiled_smart_pre_render_cancel;
     api->disable_render = _ewk_view_tiled_smart_disable_render;
     api->enable_render = _ewk_view_tiled_smart_enable_render;
index aa23fa6..a8bb56e 100644 (file)
@@ -1,3 +1,15 @@
+2012-01-06  JungJik Lee  <jungjik.lee@samsung.com>
+
+        [EFL] Add pre-render handling code in EWebLauncher.
+        https://bugs.webkit.org/show_bug.cgi?id=73430
+
+        Reviewed by Zoltan Herczeg.
+
+        Add pre-render handling code by pressing Insert key.
+
+        * EWebLauncher/main.c:
+        (on_key_down):
+
 2012-01-06  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         NRWT should use test_expectation.txt on wk2 platforms
index 1118183..2d64d4a 100644 (file)
@@ -548,6 +548,9 @@ on_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
     } else if (!strcmp(ev->key, "e")) {
         info("Render resumed");
         ewk_view_enable_render(obj);
+    } else if (!strcmp(ev->key, "Insert")) {
+        info("Pre-rendering start");
+        ewk_view_pre_render_start(obj);
     }
 }