Browse Source

GDS optimization

philippe44 1 year ago
parent
commit
e85a3cddf1

+ 0 - 6
components/display/SH1122.c

@@ -88,11 +88,6 @@ static void Update( struct GDS_Device* Device ) {
 #endif	
 }
 
-static void DrawPixelFast4( struct GDS_Device* Device, int X, int Y, int Color ) {
-    uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
-	*FBOffset = X & 0x01 ? ((*FBOffset & 0xf0) | (Color & 0x0f)) : (*FBOffset & 0x0f) | ((Color & 0x0f) << 4);
-}
-
 static void SetLayout( struct GDS_Device* Device, struct GDS_Layout *Layout ) { 
     if (Layout->HFlip) {
         Device->WriteCommand( Device, 0x40 + 0x20 );
@@ -165,7 +160,6 @@ static bool Init( struct GDS_Device* Device ) {
 
 static const struct GDS_Device SH1122 = {
 	.DisplayOn = DisplayOn, .DisplayOff = DisplayOff, .SetContrast = SetContrast,
-    .DrawPixelFast = DrawPixelFast4, 
 	.SetLayout = SetLayout,
 	.Update = Update, .Init = Init,
 	.Mode = GDS_GRAYSCALE, .Depth = 4,

+ 71 - 5
components/display/core/gds.c

@@ -109,7 +109,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
 				int c = x1;
 				// for a row that is not on a boundary, no optimization possible
 				while (r & 0x07 && r <= y2) {
-					for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color );
+					for (c = x1; c <= x2; c++) Device->DrawPixelFast( Device, c, r, Color );
 					r++;
 				}
 				// go fast if we have more than 8 lines to write
@@ -117,7 +117,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
 					memset(optr + Width * r + x1, _Color, x2 - x1 + 1);
 					r += 8;
 				} else while (r <= y2) {
-					for (c = x1; c <= x2; c++) DrawPixelFast( Device, c, r, Color );
+					for (c = x1; c <= x2; c++) Device->DrawPixelFast( Device, c, r, Color );
 					r++;
 				}
 			}
@@ -133,10 +133,10 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
 			// try to do byte processing as much as possible
 			for (int r = y1; r <= y2; r++) {
 				int c = x1;
-				if (c & 0x01) DrawPixelFast( Device, c++, r, Color);
+				if (c & 0x01) Device->DrawPixelFast( Device, c++, r, Color);
 				int chunk = (x2 - c + 1) >> 1;
 				memset(optr + ((r * Width + c)  >> 1), _Color, chunk);
-				if (c + chunk <= x2) DrawPixelFast( Device, x2, r, Color);
+				if (c + chunk <= x2) Device->DrawPixelFast( Device, x2, r, Color);
 			}
 		}	
 	} else if (Device->Depth == 8) {
@@ -148,7 +148,7 @@ void GDS_ClearWindow( struct GDS_Device* Device, int x1, int y1, int x2, int y2,
 	} else {
 		for (int y = y1; y <= y2; y++) {
 			for (int x = x1; x <= x2; x++) {
-				DrawPixelFast( Device, x, y, Color);
+				Device->DrawPixelFast( Device, x, y, Color);
 			}
 		}
 	}
@@ -171,10 +171,76 @@ bool GDS_Reset( struct GDS_Device* Device ) {
     return true;
 }
 
+static void IRAM_ATTR DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+    uint32_t YBit = ( Y & 0x07 );
+    uint8_t* FBOffset;
+
+    /* 
+     * We only need to modify the Y coordinate since the pitch
+     * of the screen is the same as the width.
+     * Dividing Y by 8 gives us which row the pixel is in but not
+     * the bit position.
+     */
+    Y>>= 3;
+
+    FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X );
+
+    if ( Color == GDS_COLOR_XOR ) {
+        *FBOffset ^= BIT( YBit );
+    } else {
+        *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( YBit ) : *FBOffset | BIT( YBit );
+    }
+}
+
+static void IRAM_ATTR DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+	uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
+	*FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f));
+}
+
+static void IRAM_ATTR DrawPixel4FastHigh( struct GDS_Device* Device, int X, int Y, int Color ) {
+    uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
+	*FBOffset = X & 0x01 ? ((*FBOffset & 0xf0) | (Color & 0x0f)) : (*FBOffset & 0x0f) | ((Color & 0x0f) << 4);
+}
+
+static void IRAM_ATTR DrawPixel8Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+	Device->Framebuffer[Y * Device->Width + X] = Color;
+}
+
+// assumes that Color is 16 bits R..RG..GB..B from MSB to LSB and FB wants 1st serialized byte to start with R
+static void IRAM_ATTR DrawPixel16Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+	uint16_t* FBOffset = (uint16_t*) Device->Framebuffer + Y * Device->Width + X;
+	*FBOffset = __builtin_bswap16(Color);
+}
+
+// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B 
+// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB 
+static void IRAM_ATTR DrawPixel18Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+	uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
+	*FBOffset++ = Color >> 12; *FBOffset++ = (Color >> 6) & 0x3f; *FBOffset = Color & 0x3f;
+}
+
+// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B 
+// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB 
+static void IRAM_ATTR DrawPixel24Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
+	uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
+	*FBOffset++ = Color >> 16; *FBOffset++ = Color >> 8; *FBOffset = Color;
+}
+
 bool GDS_Init( struct GDS_Device* Device ) {
 	
 	if (Device->Depth > 8) Device->FramebufferSize = Device->Width * Device->Height * ((8 + Device->Depth - 1) / 8);
 	else Device->FramebufferSize = (Device->Width * Device->Height) / (8 / Device->Depth);
+    
+    // set the proper DrawPixel function if not already set by driver
+    if (!Device->DrawPixelFast) {
+        if (Device->Depth == 1) Device->DrawPixelFast = DrawPixel1Fast;
+        else if (Device->Depth == 4 && Device->HighNibble) Device->DrawPixelFast = DrawPixel4FastHigh;
+        else if (Device->Depth == 4) Device->DrawPixelFast = DrawPixel4Fast;
+        else if (Device->Depth == 8) Device->DrawPixelFast = DrawPixel8Fast;	
+        else if (Device->Depth == 16) Device->DrawPixelFast = DrawPixel16Fast;	
+        else if (Device->Depth == 24 && Device->Mode == GDS_RGB666) Device->DrawPixelFast = DrawPixel18Fast;	
+        else if (Device->Depth == 24 && Device->Mode == GDS_RGB888) Device->DrawPixelFast = DrawPixel24Fast;	
+    }	
 	
 	// allocate FB unless explicitely asked not to
 	if (!(Device->Alloc & GDS_ALLOC_NONE)) {

+ 12 - 12
components/display/core/gds_draw.c

@@ -45,7 +45,7 @@ __attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b )
 }
 
 void IRAM_ATTR GDS_DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	DrawPixelFast( Device, X, Y, Color );
+	Device->DrawPixelFast( Device, X, Y, Color );
 }
 
 void IRAM_ATTR GDS_DrawPixel( struct GDS_Device* Device, int X, int Y, int Color ) {
@@ -63,7 +63,7 @@ void GDS_DrawHLine( struct GDS_Device* Device, int x, int y, int Width, int Colo
 	if (y < 0) y = 0;
 	else if (y >= Device->Height) y = Device->Height - 1;
 
-    for ( ; x < XEnd; x++ ) DrawPixelFast( Device, x, y, Color );
+    for ( ; x < XEnd; x++ ) Device->DrawPixelFast( Device, x, y, Color );
 }
 
 void GDS_DrawVLine( struct GDS_Device* Device, int x, int y, int Height, int Color ) {
@@ -97,7 +97,7 @@ static inline void DrawWideLine( struct GDS_Device* Device, int x0, int y0, int
 
     for ( ; x < x1; x++ ) {
         if ( IsPixelVisible( Device, x, y ) == true ) {
-            DrawPixelFast( Device, x, y, Color );
+            Device->DrawPixelFast( Device, x, y, Color );
         }
 
         if ( Error > 0 ) {
@@ -126,7 +126,7 @@ static inline void DrawTallLine( struct GDS_Device* Device, int x0, int y0, int
 
     for ( ; y < y1; y++ ) {
         if ( IsPixelVisible( Device, x, y ) == true ) {
-            DrawPixelFast( Device, x, y, Color );
+            Device->DrawPixelFast( Device, x, y, Color );
         }
 
         if ( Error > 0 ) {
@@ -348,14 +348,14 @@ void GDS_DrawBitmapCBR(struct GDS_Device* Device, uint8_t *Data, int Width, int
 		// don't know bitdepth, use brute-force solution
 		for (int i = Width * Height, r = 0, c = 0; --i >= 0;) {
 			uint8_t Byte = *Data++;
-			DrawPixelFast( Device, c, (r << 3) + 7, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 6, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 5, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 4, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 3, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 2, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 1, (Byte & 0x01) * Color ); Byte >>= 1;
-			DrawPixelFast( Device, c, (r << 3) + 0, (Byte & 0x01) * Color ); 
+			Device->DrawPixelFast( Device, c, (r << 3) + 7, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 6, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 5, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 4, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 3, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 2, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 1, (Byte & 0x01) * Color ); Byte >>= 1;
+			Device->DrawPixelFast( Device, c, (r << 3) + 0, (Byte & 0x01) * Color ); 
 			if (++r == Height) { c++; r = 0; }			
 		}
 		/* for better understanding, here is the mundane version 

+ 1 - 61
components/display/core/gds_private.h

@@ -156,69 +156,9 @@ static inline bool IsPixelVisible( struct GDS_Device* Device, int x, int y )  {
     return Result;
 }
 
-static inline void DrawPixel1Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-    uint32_t YBit = ( Y & 0x07 );
-    uint8_t* FBOffset;
-
-    /* 
-     * We only need to modify the Y coordinate since the pitch
-     * of the screen is the same as the width.
-     * Dividing Y by 8 gives us which row the pixel is in but not
-     * the bit position.
-     */
-    Y>>= 3;
-
-    FBOffset = Device->Framebuffer + ( ( Y * Device->Width ) + X );
-
-    if ( Color == GDS_COLOR_XOR ) {
-        *FBOffset ^= BIT( YBit );
-    } else {
-        *FBOffset = ( Color == GDS_COLOR_BLACK ) ? *FBOffset & ~BIT( YBit ) : *FBOffset | BIT( YBit );
-    }
-}
-
-static inline void DrawPixel4Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	uint8_t* FBOffset = Device->Framebuffer + ( (Y * Device->Width >> 1) + (X >> 1));
-	*FBOffset = X & 0x01 ? (*FBOffset & 0x0f) | ((Color & 0x0f) << 4) : ((*FBOffset & 0xf0) | (Color & 0x0f));
-}
-
-static inline void DrawPixel8Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	Device->Framebuffer[Y * Device->Width + X] = Color;
-}
-
-// assumes that Color is 16 bits R..RG..GB..B from MSB to LSB and FB wants 1st serialized byte to start with R
-static inline void DrawPixel16Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	uint16_t* FBOffset = (uint16_t*) Device->Framebuffer + Y * Device->Width + X;
-	*FBOffset = __builtin_bswap16(Color);
-}
-
-// assumes that Color is 18 bits RGB from MSB to LSB RRRRRRGGGGGGBBBBBB, so byte[0] is B 
-// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = xxRRRRRR xxGGGGGG xxBBBBBB 
-static inline void DrawPixel18Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
-	*FBOffset++ = Color >> 12; *FBOffset++ = (Color >> 6) & 0x3f; *FBOffset = Color & 0x3f;
-}
-
-// assumes that Color is 24 bits RGB from MSB to LSB RRRRRRRRGGGGGGGGBBBBBBBB, so byte[0] is B 
-// FB is 3-bytes packets and starts with R for serialization so 0,1,2 ... = RRRRRRRR GGGGGGGG BBBBBBBB 
-static inline void DrawPixel24Fast( struct GDS_Device* Device, int X, int Y, int Color ) {
-	uint8_t* FBOffset = Device->Framebuffer + (Y * Device->Width + X) * 3;
-	*FBOffset++ = Color >> 16; *FBOffset++ = Color >> 8; *FBOffset = Color;
-}
-
-static inline void IRAM_ATTR DrawPixelFast( struct GDS_Device* Device, int X, int Y, int Color ) {
-    if (Device->DrawPixelFast) Device->DrawPixelFast( Device, X, Y, Color );
-	else if (Device->Depth == 4) DrawPixel4Fast( Device, X, Y, Color );
-	else if (Device->Depth == 1) DrawPixel1Fast( Device, X, Y, Color );
-	else if (Device->Depth == 16) DrawPixel16Fast( Device, X, Y, Color );	
-	else if (Device->Depth == 24 && Device->Mode == GDS_RGB666) DrawPixel18Fast( Device, X, Y, Color );	
-	else if (Device->Depth == 24 && Device->Mode == GDS_RGB888) DrawPixel24Fast( Device, X, Y, Color );	
-	else if (Device->Depth == 8) DrawPixel8Fast( Device, X, Y, Color );	
-}	
-
 static inline void IRAM_ATTR DrawPixel( struct GDS_Device* Device, int x, int y, int Color ) {
     if ( IsPixelVisible( Device, x, y ) == true ) {
-        DrawPixelFast( Device, x, y, Color );
+        Device->DrawPixelFast( Device, x, y, Color );
     }
 }
 

+ 1 - 1
components/display/core/gds_text.c

@@ -108,7 +108,7 @@ bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Tex
 		int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height);
 		for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++) 
 			for (int y = Y_min; y < Y_max; y++)
-				DrawPixelFast( Device, c, y, GDS_COLOR_BLACK );
+				Device->DrawPixelFast( Device, c, y, GDS_COLOR_BLACK );
 	}
 		
 	GDS_FontDrawString( Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE );