Browse Source

WWLCDPanel has two bitmap data, and the bitmap once drawn is
Fixed not to draw. Reduced the load on the X server.
(Improvements related to WWLCDPanel and XDisplay_DrawLCDWindow () of XDisplay.c)
(XDisplay_DrawLCDWindow () in XDisplay.c has useless malloc ()
Improvement is necessary of that)

In WWDisplay.c (WWDisplay_DrawScreen ()) of wonx-a 05 and wonx-a 06
As a result of trying both, wonx - a 05 was faster, so wonx - a 05 was better
I decided to use it.

Version 0.0.7 alpha - from wonx-a07.tar.gz

Hiroaki Sakai 23 years ago
parent
commit
95d1135996
7 changed files with 212 additions and 108 deletions
  1. 17 0
      HISTORY
  2. 2 2
      Makefile
  3. 99 91
      WWDisplay.c
  4. 61 12
      WWLCDPanel.c
  5. 8 0
      WWLCDPanel.h
  6. 13 2
      WWLCDPanelP.h
  7. 12 1
      XDisplay.c

+ 17 - 0
HISTORY

@@ -1,3 +1,20 @@
+2000/10/5(木)
+
+wonx-a07 公開
+
+WWLCDPanel にビットマップデータを2枚持たせ,一度描画したビットマップは
+描画しないように修正.Xサーバの負荷を減らした.
+(WWLCDPanel関連と,XDisplay.c の XDisplay_DrawLCDWindow() を改良)
+(XDisplay.c の XDisplay_DrawLCDWindow() には,無駄な malloc() があるので,
+ そのうち改良が必要)
+
+wonx-a05 と wonx-a06 の WWDisplay.c (WWDisplay_DrawScreen()) の
+両方を試した結果,wonx-a05 のほうが高速だったので,wonx-a05 のほうを
+使用することにした.
+
+
+
+
 2000/10/4(水)
 
 wonx-a06 公開

+ 2 - 2
Makefile

@@ -2,8 +2,8 @@ XINCLUDEDIR = /usr/X11R6/include
 INCLUDEDIR = .
 XLIBDIR = /usr/X11R6/lib
 
-VERSION = Wonx-a06
-PKGNAME = wonx-a06
+VERSION = Wonx-a07
+PKGNAME = wonx-a07
 
 OBJS = WWCharacter.o WWColorMap.o WWDisplay.o WWLCDPanel.o WWPalette.o WWScreen.o WWSprite.o WonxDisplay.o XDisplay.o bank.o comm.o disp.o text.o key.o sound.o system.o timer.o etc.o wonx.o
 

+ 99 - 91
WWDisplay.c

@@ -195,14 +195,22 @@ WWDisplay WWDisplay_Destroy(WWDisplay display)
 /* LCDパネルの描画                                                           */
 /*===========================================================================*/
 
-static int WWDisplay_DrawScreen(WWDisplay display, WWScreen screen,
-				int lcd_x, int lcd_y)
+static int WWDisplay_DrawScreen(WWDisplay display, WWScreen screen)
 {
+  WWLCDPanel lcd_panel;
+  int lcd_panel_width;
+  int lcd_panel_height;
+
   int pixel;
-  int px, py;
+  int x, y, px, py;
   int sx, sy, ex, ey;
+  int mode;
+
+  if (!WWScreen_GetEnable(screen)) return (0);
 
-  if (!WWScreen_GetEnable(screen)) return (-1);
+  lcd_panel = WWDisplay_GetLCDPanel(display);
+  lcd_panel_width  = WWLCDPanel_GetWidth( lcd_panel);
+  lcd_panel_height = WWLCDPanel_GetHeight(lcd_panel);
 
   if ( (WWScreen_GetMode(screen) == WWSCREEN_INSIDE_ONLY) ||
        (WWScreen_GetMode(screen) == WWSCREEN_OUTSIDE_ONLY) ) {
@@ -229,35 +237,50 @@ static int WWDisplay_DrawScreen(WWDisplay display, WWScreen screen,
 #endif
   }
 
-  switch (WWScreen_GetMode(screen)) {
-  case WWSCREEN_INSIDE_ONLY:
-    if ( (lcd_x < sx) || (lcd_x > ex) || (lcd_y < sy) || (lcd_y > ey) )
-      return (-1);
-    break;
-  case WWSCREEN_OUTSIDE_ONLY:
-    if ( !( (lcd_x < sx) || (lcd_x > ex) || (lcd_y < sy) || (lcd_y > ey) ) )
-      return (-1);
-    break;
-  }
+  mode = WWScreen_GetMode(screen);
+
+  /* 以下はホットスポットになるので,そのうちループアンローリング */
+  /* したほうがいいかも                                           */
 
-  px = lcd_x + WWScreen_GetRollX(screen);
-  py = lcd_y + WWScreen_GetRollY(screen);
+  for (y = 0; y < lcd_panel_height; y++) {
 
-  pixel = WWScreen_GetPixel(screen, px, py);
+    if (mode == WWSCREEN_INSIDE_ONLY) {
+      if (y > ey) { break; }
+      if (y < sy) { y = sy - 1; continue; }
+    }
+
+    py = y + WWScreen_GetRollY(screen);
+
+    for (x = 0; x < lcd_panel_width; x++) {
+
+      if (mode == WWSCREEN_INSIDE_ONLY) {
+	if (x > ex) { x = lcd_panel_width - 1; continue; }
+	if (x < sx) { x = sx - 1; continue; }
+      } else if (mode == WWSCREEN_OUTSIDE_ONLY) {
+	if ( (x >= sx) && (x <= ex) && (y >= sy) && (y <= ey) ) {
+	  x = ex;
+	  continue;
+	}
+      }
+
+      px = x + WWScreen_GetRollX(screen);
+
+      pixel = WWScreen_GetPixel(screen, px, py);
 
-  /* 透明色の場合 */
-  if (pixel == -1) return (-1);
+      /* 透明色の場合 */
+      if (pixel == -1) continue;
 
-  pixel = WWColorMap_GetLCDColor(WWDisplay_GetColorMap(display), pixel);
-  WWLCDPanel_SetPixel(WWDisplay_GetLCDPanel(display), lcd_x, lcd_y, pixel);
+      pixel = WWColorMap_GetLCDColor(WWDisplay_GetColorMap(display), pixel);
+      WWLCDPanel_SetPixel(lcd_panel, x, y, pixel);
+    }
+  }
 
-  return (pixel);
+  return (0);
 }
 
-static int WWDisplay_DrawSprite(WWDisplay display, WWSprite sprite,
-				int lcd_x, int lcd_y)
+static int WWDisplay_DrawSprite(WWDisplay display, WWSprite sprite)
 {
-  int x, y, sprite_x, sprite_y;
+  int x, y, lcd_x, lcd_y;
   int sx, sy, ex, ey;
   int pixel, outside;
 
@@ -273,38 +296,35 @@ static int WWDisplay_DrawSprite(WWDisplay display, WWSprite sprite,
   ey = sy + WWDisplay_GetSpriteWindowHeight(display);
 #endif
 
-  sprite_x = WWSprite_GetX(sprite);
-  sprite_y = WWSprite_GetY(sprite);
-
-  if ( (lcd_x < sprite_x) || (lcd_x > sprite_x + 7) ||
-       (lcd_y < sprite_y) || (lcd_y > sprite_y + 7) )
-    return (-1);
+  for (y = 0; y < 8; y++) {
+    for (x = 0; x < 8; x++) {
+      pixel = WWSprite_GetPixel(sprite, x, y);
 
-  x = lcd_x - sprite_x;
-  y = lcd_y - sprite_y;
+      /* 透明色の場合 */
+      if (pixel == -1) continue;
 
-  pixel = WWSprite_GetPixel(sprite, x, y);
+      lcd_x = WWSprite_GetX(sprite) + x;
+      lcd_y = WWSprite_GetY(sprite) + y;
 
-  /* 透明色の場合 */
-  if (pixel == -1) return (-1);
+      if (WWDisplay_GetSpriteWindowEnable(display)) {
+	if ( (lcd_x < sx) || (lcd_y < sy) || (lcd_x > ex) || (lcd_y > ey) )
+	  outside = 1;
+	else
+	  outside = 0;
 
-  if (WWDisplay_GetSpriteWindowEnable(display)) {
-    if ( (lcd_x < sx) || (lcd_y < sy) || (lcd_x > ex) || (lcd_y > ey) )
-      outside = 1;
-    else
-      outside = 0;
+	if (WWSprite_GetClipping(sprite)) { /* ウインドウの外側部分を表示 */
+	  if (!outside) continue;
+	} else {                            /* ウインドウの内側部分を表示 */
+	  if (outside) continue;
+	}
+      }
 
-    if (WWSprite_GetClipping(sprite)) { /* ウインドウの外側部分を表示 */
-      if (!outside) return (-1);
-    } else {                            /* ウインドウの内側部分を表示 */
-      if (outside) return (-1);
+      pixel = WWColorMap_GetLCDColor(WWDisplay_GetColorMap(display), pixel);
+      WWLCDPanel_SetPixel(WWDisplay_GetLCDPanel(display), lcd_x, lcd_y, pixel);
     }
   }
 
-  pixel = WWColorMap_GetLCDColor(WWDisplay_GetColorMap(display), pixel);
-  WWLCDPanel_SetPixel(WWDisplay_GetLCDPanel(display), lcd_x, lcd_y, pixel);
-
-  return (pixel);
+  return (0);
 }
 
 int WWDisplay_DrawLCDPanel(WWDisplay display)
@@ -317,7 +337,6 @@ int WWDisplay_DrawLCDPanel(WWDisplay display)
   WWColorMap color_map;
   int border;
   WWSprite sprite;
-  int ret;
 
   lcd_panel = WWDisplay_GetLCDPanel(display);
   lcd_panel_width  = WWLCDPanel_GetWidth( lcd_panel);
@@ -325,52 +344,41 @@ int WWDisplay_DrawLCDPanel(WWDisplay display)
   color_map = WWDisplay_GetColorMap(display);
   border = WWDisplay_GetBorder(display);
 
+  /* ボーダーカラーで埋める */
   for (x = 0; x < lcd_panel_width; x++) {
     for (y = 0; y < lcd_panel_height; y++) {
+      WWLCDPanel_SetPixel(lcd_panel, x, y,
+			  WWColorMap_GetLCDColor(color_map, border));
+    }
+  }
 
-      /* スクリーン2より優先のスプライトの描画 */
-      /* 重なった場合は,番号の若いものが手前に表示される */
-      ret = -1;
-      if (WWDisplay_GetSpriteEnable(display)) {
-	for (i = 0; i < WWDisplay_GetSpriteCount(display); i++) {
-	  sprite = WWDisplay_GetSprite(display,
-				       i + WWDisplay_GetSpriteStart(display));
-	  if (WWSprite_GetPriority(sprite)) {
-	    ret = WWDisplay_DrawSprite(display, sprite, x, y);
-	    if (ret != -1) break;
-	  }
-	}
-      }
-      if (ret != -1) continue;
-
-      /* スクリーン2の描画 */
-      ret = WWDisplay_DrawScreen(display, WWDisplay_GetScreen(display, 1),
-				 x, y);
-      if (ret != -1) continue;
-
-      /* スクリーン2より優先でないスプライトの描画 */
-      /* 重なった場合は,番号の若いものが手前に表示される */
-      ret = -1;
-      if (WWDisplay_GetSpriteEnable(display)) {
-	for (i = 0; i < WWDisplay_GetSpriteCount(display); i++) {
-	  sprite = WWDisplay_GetSprite(display,
-				       i + WWDisplay_GetSpriteStart(display));
-	  if (!WWSprite_GetPriority(sprite)) {
-	    ret = WWDisplay_DrawSprite(display, sprite, x, y);
-	    if (ret != -1) break;
-	  }
-	}
+  /* スクリーン1描画 */
+  WWDisplay_DrawScreen(display, WWDisplay_GetScreen(display, 0));
+
+  /* スプライト描画(スクリーン2より優先でないもの) */
+  /* 重なった場合は,番号の若いものが手前に表示される */
+  if (WWDisplay_GetSpriteEnable(display)) {
+    for (i = WWDisplay_GetSpriteCount(display) - 1; i >= 0; i--) {
+      sprite = WWDisplay_GetSprite(display,
+				   i + WWDisplay_GetSpriteStart(display));
+      if (!WWSprite_GetPriority(sprite)) {
+	WWDisplay_DrawSprite(display, sprite);
       }
-      if (ret != -1) continue;
-
-      /* スクリーン1の描画 */
-      ret = WWDisplay_DrawScreen(display, WWDisplay_GetScreen(display, 0),
-				 x, y);
-      if (ret != -1) continue;
+    }
+  }
 
-      /* ボーダーカラーの描画 */
-      WWLCDPanel_SetPixel(lcd_panel, x, y,
-			  WWColorMap_GetLCDColor(color_map, border));
+  /* スクリーン2描画 */
+  WWDisplay_DrawScreen(display, WWDisplay_GetScreen(display, 1));
+
+  /* スプライト描画(スクリーン2より優先なもの) */
+  /* 重なった場合は,番号の若いものが手前に表示される */
+  if (WWDisplay_GetSpriteEnable(display)) {
+    for (i = WWDisplay_GetSpriteCount(display) - 1; i >= 0; i--) {
+      sprite = WWDisplay_GetSprite(display,
+				   i + WWDisplay_GetSpriteStart(display));
+      if (WWSprite_GetPriority(sprite)) {
+	WWDisplay_DrawSprite(display, sprite);
+      }
     }
   }
 

+ 61 - 12
WWLCDPanel.c

@@ -13,52 +13,95 @@ int WWLCDPanel_GetHeight(WWLCDPanel p) { return (p->height); }
 int WWLCDPanel_SetWidth( WWLCDPanel p, int n) { return (p->width  = n); }
 int WWLCDPanel_SetHeight(WWLCDPanel p, int n) { return (p->height = n); }
 
-unsigned char * WWLCDPanel_GetPixelMap(WWLCDPanel p) { return (p->pixel); }
+int WWLCDPanel_ResetCurrent(WWLCDPanel p)
+{
+  return (p->current = 0);
+}
+
+int WWLCDPanel_ReverseCurrent(WWLCDPanel p)
+{
+  return (p->current = 1 - p->current);
+}
+
+int WWLCDPanel_ResetAllDraw(WWLCDPanel p) { return (p->all_draw = 0); }
+int WWLCDPanel_SetAllDraw(WWLCDPanel p)   { return (p->all_draw = 1); }
+int WWLCDPanel_IsAllDraw(WWLCDPanel p)   { return (p->all_draw); }
+
+unsigned char * WWLCDPanel_GetPixelMap(WWLCDPanel p)
+{
+  return (p->pixel[p->current]);
+}
 
 /* LCDは1ピクセル16色(4ビット必要) */
-int WWLCDPanel_GetPixel(WWLCDPanel lcd_panel, int x, int y)
+static int WWLCDPanel_GetPixelByCurrent(WWLCDPanel lcd_panel, int current,
+					int x, int y)
 {
   unsigned char pixel;
 
-  if ( (x < 0) || (x > WWLCDPanel_GetWidth(lcd_panel) - 1) ||
+  if ( (x < 0) || (x > WWLCDPanel_GetWidth( lcd_panel) - 1) ||
        (y < 0) || (y > WWLCDPanel_GetHeight(lcd_panel) - 1) )
     return (-1);
 
-  pixel = lcd_panel->pixel[y * WWLCDPanel_GetWidth(lcd_panel) + x];
+  pixel = lcd_panel->pixel[current][y * WWLCDPanel_GetWidth(lcd_panel) + x];
   pixel &= 0x0f;
   return ((int)pixel);
 }
 
+static int WWLCDPanel_GetOldPixel(WWLCDPanel lcd_panel, int x, int y)
+{
+  return (WWLCDPanel_GetPixelByCurrent(lcd_panel, 1 - lcd_panel->current, x, y));
+}
+
+int WWLCDPanel_GetPixel(WWLCDPanel lcd_panel, int x, int y)
+{
+  return (WWLCDPanel_GetPixelByCurrent(lcd_panel, lcd_panel->current, x, y));
+}
+
 int WWLCDPanel_SetPixel(WWLCDPanel lcd_panel, int x, int y, int pixel)
 {
   unsigned char p;
   int n;
 
-  if ( (x < 0) || (x > WWLCDPanel_GetWidth(lcd_panel) - 1) ||
+  if ( (x < 0) || (x > WWLCDPanel_GetWidth( lcd_panel) - 1) ||
        (y < 0) || (y > WWLCDPanel_GetHeight(lcd_panel) - 1) )
     return (-1);
 
   p = ((unsigned char)pixel) & 0x0f;
   n = y * WWLCDPanel_GetWidth(lcd_panel) + x;
-  lcd_panel->pixel[n] = p;
+  lcd_panel->pixel[lcd_panel->current][n] = p;
 
   return (pixel);
 }
 
+int WWLCDPanel_IsPixelChanged(WWLCDPanel lcd_panel, int x, int y)
+{
+  int old_pixel;
+  int current_pixel;
+
+  if (WWLCDPanel_IsAllDraw(lcd_panel)) return (1);
+  old_pixel = WWLCDPanel_GetOldPixel(lcd_panel, x, y);
+  current_pixel = WWLCDPanel_GetPixel(lcd_panel, x, y);
+
+  return (!(old_pixel == current_pixel));
+}
+
 WWLCDPanel WWLCDPanel_Create(int width, int height)
 {
   WWLCDPanel lcd_panel;
-  int x, y;
+  int x, y, i;
 
   lcd_panel = (WWLCDPanel)malloc(sizeof(_WWLCDPanel));
   if (lcd_panel == NULL) Error("WWLCDPanel_Create", "Cannot allocate memory.");
 
   WWLCDPanel_SetWidth( lcd_panel, width);
   WWLCDPanel_SetHeight(lcd_panel, height);
-  lcd_panel->pixel =
-    (unsigned char *)malloc(sizeof(unsigned char) *
-			    WWLCDPanel_GetWidth(lcd_panel) *
-			    WWLCDPanel_GetHeight(lcd_panel));
+
+  for (i = 0; i < 2; i++) {
+    lcd_panel->pixel[i] =
+      (unsigned char *)malloc(sizeof(unsigned char) *
+			      WWLCDPanel_GetWidth(lcd_panel) *
+			      WWLCDPanel_GetHeight(lcd_panel));
+  }
 
   for (y = 0; y < lcd_panel->height; y++) {
     for (x = 0; x < lcd_panel->width / 2; x++) {
@@ -66,13 +109,19 @@ WWLCDPanel WWLCDPanel_Create(int width, int height)
     }
   }
 
+  WWLCDPanel_ResetCurrent(lcd_panel);
+  WWLCDPanel_SetAllDraw(lcd_panel); /* 初回は全画面を描画する */
+
   return (lcd_panel);
 }
 
 WWLCDPanel WWLCDPanel_Destroy(WWLCDPanel lcd_panel)
 {
+  int i;
   if (lcd_panel == NULL) return (NULL);
-  if (lcd_panel->pixel) free(lcd_panel->pixel);
+  for (i = 0; i < 2; i++) {
+    if (lcd_panel->pixel[i]) free(lcd_panel->pixel[i]);
+  }
   free(lcd_panel);
   return (NULL);
 }

+ 8 - 0
WWLCDPanel.h

@@ -21,9 +21,17 @@ int WWLCDPanel_GetWidth( WWLCDPanel p);
 int WWLCDPanel_GetHeight(WWLCDPanel p);
 int WWLCDPanel_SetWidth( WWLCDPanel p, int n);
 int WWLCDPanel_SetHeight(WWLCDPanel p, int n);
+
+int WWLCDPanel_ResetCurrent(WWLCDPanel p);
+int WWLCDPanel_ReverseCurrent(WWLCDPanel p);
+int WWLCDPanel_ResetAllDraw(WWLCDPanel p);
+int WWLCDPanel_SetAllDraw(WWLCDPanel p);
+int WWLCDPanel_IsAllDraw(WWLCDPanel p);
+
 unsigned char * WWLCDPanel_GetPixelMap(WWLCDPanel p);
 int WWLCDPanel_GetPixel(WWLCDPanel lcd_panel, int x, int y);
 int WWLCDPanel_SetPixel(WWLCDPanel lcd_panel, int x, int y, int pixel);
+int WWLCDPanel_IsPixelChanged(WWLCDPanel lcd_panel, int x, int y);
 WWLCDPanel WWLCDPanel_Create(int width, int height);
 WWLCDPanel WWLCDPanel_Destroy(WWLCDPanel lcd_panel);
 

+ 13 - 2
WWLCDPanelP.h

@@ -14,8 +14,19 @@
 typedef struct _WWLCDPanel {
   int width;
   int height;
-  /* 16色のカラー情報.1バイトで2ピクセル分の情報を持つ */
-  unsigned char * pixel;
+
+  /* Xサーバの負荷を減らすため,ビットマップを2枚持ち, */
+  /* 前回と同じ部分は書き換えないようにする.            */
+  /* pixel[current] が現在描画中のビットマップになる.   */
+  /* pixel[1 - current] が前回のビットマップになる.     */
+  int current;
+
+  /* all_draw == 1 のときは,前回分が無いので,          */
+  /* 全部描画することを示す.                            */
+  int all_draw;
+
+  /* 16色のカラー情報.1バイトで1ピクセル分の情報を持つ */
+  unsigned char * pixel[2];
 } _WWLCDPanel;
 
 /*****************************************************************************/

+ 12 - 1
XDisplay.c

@@ -371,6 +371,10 @@ int XDisplay_DrawLCDWindow(XDisplay x_display, WWLCDPanel ww_lcd_panel)
   num =
     WWLCDPanel_GetHeight(ww_lcd_panel) * WWLCDPanel_GetWidth(ww_lcd_panel) / 2;
 
+  /*
+   * この malloc() は,実際にはメモリはほとんど使用されていないので,
+   * そのうちなんとかする必要がある
+   */
   for (pixel = 0; pixel < 16; pixel++) {
     n[pixel] = 0;
     rectangles[pixel] = (XRectangle *)malloc(sizeof(XRectangle) * num);
@@ -387,6 +391,9 @@ int XDisplay_DrawLCDWindow(XDisplay x_display, WWLCDPanel ww_lcd_panel)
     py = (y * x_display->height) / ww_lcd_height;
     ph = (y+1) * x_display->height / ww_lcd_height- py;
     for (x = 0; x < ww_lcd_width; x++) {
+      if (!WWLCDPanel_IsPixelChanged(ww_lcd_panel, x, y)) {
+	continue;
+      }
       pixel = WWLCDPanel_GetPixel(ww_lcd_panel, x, y);
       px = (x * x_display->width ) / ww_lcd_width;
       rectangles[pixel][n[pixel]].x = px;
@@ -398,7 +405,8 @@ int XDisplay_DrawLCDWindow(XDisplay x_display, WWLCDPanel ww_lcd_panel)
       /* 隣接してる同色のピクセルは,極力いっしょに描画する */
       x++;
       while ( (x < ww_lcd_width) &&
-	      (pixel == WWLCDPanel_GetPixel(ww_lcd_panel, x, y)) ) {
+	      (pixel == WWLCDPanel_GetPixel(ww_lcd_panel, x, y)) &&
+	      (WWLCDPanel_IsPixelChanged(ww_lcd_panel, x, y)) ) {
 	rectangles[pixel][n[pixel]].width =
 	  (x+1) * x_display->width / ww_lcd_width - px;
 	x++;
@@ -422,6 +430,9 @@ int XDisplay_DrawLCDWindow(XDisplay x_display, WWLCDPanel ww_lcd_panel)
 	    x_display->lcd_window, x_display->copy_gc,
             0, 0, x_display->width, x_display->height, 0, 0);
 
+  WWLCDPanel_ResetAllDraw(ww_lcd_panel);
+  WWLCDPanel_ReverseCurrent(ww_lcd_panel);
+
   XDisplay_Sync(x_display);
 
   for (pixel = 0; pixel < 16; pixel++) {