Browse Source

[fbcon] Centre background picture on console

Centre the background picture on the console, to give a more
consistent result when the aspect ratio does not match the requested
width and height.

Once drawn for the first time, nothing should ever overwrite the
margins of the display.  We can therefore eliminate the logic used to
redraw only the margin areas, and use much simpler code to draw the
complete initial background image.

Simplify the redrawing logic further by making the background picture
buffer equal in size to the frame buffer.  In the common case of a
background picture which is designed to fill the screen, this wastes
no extra memory, and the combined code simplifications reduce the size
of fbcon.o by approximately 15%.

Redefine the concept of "margin" to match the intuitive definition
(i.e. the size of the gap, rather than the position of the boundary
line).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
7fc380e950
2 changed files with 116 additions and 251 deletions
  1. 116
    243
      src/core/fbcon.c
  2. 0
    8
      src/include/ipxe/fbcon.h

+ 116
- 243
src/core/fbcon.c View File

98
 	fbcon->background = FBCON_TRANSPARENT;
98
 	fbcon->background = FBCON_TRANSPARENT;
99
 }
99
 }
100
 
100
 
101
+/**
102
+ * Clear rows of characters
103
+ *
104
+ * @v fbcon		Frame buffer console
105
+ * @v ypos		Starting Y position
106
+ */
107
+static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
108
+	struct fbcon_text_cell cell = {
109
+		.foreground = fbcon->foreground,
110
+		.background = fbcon->background,
111
+		.character = ' ',
112
+	};
113
+	size_t offset;
114
+	unsigned int xpos;
115
+
116
+	/* Clear stored character array */
117
+	for ( ; ypos < fbcon->character.height ; ypos++ ) {
118
+		offset = ( ypos * fbcon->character.width * sizeof ( cell ) );
119
+		for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) {
120
+			copy_to_user ( fbcon->text.start, offset, &cell,
121
+				       sizeof ( cell ) );
122
+			offset += sizeof ( cell );
123
+		}
124
+	}
125
+}
126
+
101
 /**
127
 /**
102
  * Store character at specified position
128
  * Store character at specified position
103
  *
129
  *
106
  * @v xpos		X position
132
  * @v xpos		X position
107
  * @v ypos		Y position
133
  * @v ypos		Y position
108
  */
134
  */
109
-static void fbcon_store_character ( struct fbcon *fbcon,
110
-				    struct fbcon_text_cell *cell,
111
-				    unsigned int xpos, unsigned int ypos ) {
135
+static void fbcon_store ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
136
+			  unsigned int xpos, unsigned int ypos ) {
112
 	size_t offset;
137
 	size_t offset;
113
 
138
 
114
 	/* Store cell */
139
 	/* Store cell */
125
  * @v xpos		X position
150
  * @v xpos		X position
126
  * @v ypos		Y position
151
  * @v ypos		Y position
127
  */
152
  */
128
-static void fbcon_draw_character ( struct fbcon *fbcon,
129
-				   struct fbcon_text_cell *cell,
130
-				   unsigned int xpos, unsigned int ypos ) {
131
-	static uint32_t black[FBCON_CHAR_WIDTH];
153
+static void fbcon_draw ( struct fbcon *fbcon, struct fbcon_text_cell *cell,
154
+			 unsigned int xpos, unsigned int ypos ) {
132
 	struct fbcon_font_glyph glyph;
155
 	struct fbcon_font_glyph glyph;
133
-	userptr_t picture_start;
134
-	size_t picture_offset;
135
-	size_t picture_stride;
136
 	size_t offset;
156
 	size_t offset;
137
 	size_t pixel_len;
157
 	size_t pixel_len;
138
 	size_t skip_len;
158
 	size_t skip_len;
154
 	pixel_len = fbcon->pixel->len;
174
 	pixel_len = fbcon->pixel->len;
155
 	skip_len = ( fbcon->pixel->stride - fbcon->character.len );
175
 	skip_len = ( fbcon->pixel->stride - fbcon->character.len );
156
 
176
 
157
-	/* Calculate background picture geometry */
158
-	if ( ( xpos < fbcon->picture.character.width ) &&
159
-	     ( ypos < fbcon->picture.character.height ) ) {
160
-		picture_start = fbcon->picture.start;
161
-		picture_offset = ( fbcon->picture.indent +
162
-				   ( ypos * fbcon->picture.character.stride ) +
163
-				   ( xpos * fbcon->picture.character.len ) );
164
-		picture_stride = fbcon->picture.pixel.stride;
165
-	} else {
166
-		picture_start = virt_to_user ( black );
167
-		picture_offset = 0;
168
-		picture_stride = 0;
169
-	}
170
-	assert ( fbcon->character.len <= sizeof ( black ) );
171
-
172
 	/* Check for transparent background colour */
177
 	/* Check for transparent background colour */
173
 	transparent = ( cell->background == FBCON_TRANSPARENT );
178
 	transparent = ( cell->background == FBCON_TRANSPARENT );
174
 
179
 
175
 	/* Draw character rows */
180
 	/* Draw character rows */
176
 	for ( row = 0 ; row < FBCON_CHAR_HEIGHT ; row++ ) {
181
 	for ( row = 0 ; row < FBCON_CHAR_HEIGHT ; row++ ) {
177
 
182
 
178
-		/* Draw background picture */
179
-		memcpy_user ( fbcon->start, offset, picture_start,
180
-			      picture_offset, fbcon->character.len );
183
+		/* Draw background picture, if applicable */
184
+		if ( transparent ) {
185
+			if ( fbcon->picture.start ) {
186
+				memcpy_user ( fbcon->start, offset,
187
+					      fbcon->picture.start, offset,
188
+					      fbcon->character.len );
189
+			} else {
190
+				memset_user ( fbcon->start, offset, 0,
191
+					      fbcon->character.len );
192
+			}
193
+		}
181
 
194
 
182
 		/* Draw character row */
195
 		/* Draw character row */
183
 		for ( column = FBCON_CHAR_WIDTH, bitmask = glyph.bitmask[row] ;
196
 		for ( column = FBCON_CHAR_WIDTH, bitmask = glyph.bitmask[row] ;
194
 
207
 
195
 		/* Move to next row */
208
 		/* Move to next row */
196
 		offset += skip_len;
209
 		offset += skip_len;
197
-		picture_offset += picture_stride;
198
 	}
210
 	}
199
 }
211
 }
200
 
212
 
201
 /**
213
 /**
202
- * Redraw margins
214
+ * Redraw all characters
203
  *
215
  *
204
  * @v fbcon		Frame buffer console
216
  * @v fbcon		Frame buffer console
205
  */
217
  */
206
-static void fbcon_redraw_margins ( struct fbcon *fbcon ) {
207
-	struct fbcon_picture *picture = &fbcon->picture;
208
-	size_t pixel_len = fbcon->pixel->len;
209
-	size_t offset = 0;
210
-	size_t picture_offset = 0;
211
-	size_t row_len;
212
-	size_t left_len;
213
-	size_t right_len;
214
-	size_t right_offset;
215
-	unsigned int y;
216
-
217
-	/* Calculate margin parameters */
218
-	row_len = ( picture->pixel.width * pixel_len );
219
-	left_len = ( picture->margin.left * pixel_len );
220
-	right_offset = ( picture->margin.right * pixel_len );
221
-	right_len = ( ( picture->pixel.width - picture->margin.right ) *
222
-		      pixel_len );
223
-
224
-	/* Redraw margins */
225
-	for ( y = 0 ; y < picture->pixel.height ; y++ ) {
226
-		if ( ( y < picture->margin.top ) ||
227
-		     ( y >= picture->margin.bottom ) ) {
228
-
229
-			/* Within top or bottom margin: draw whole row */
230
-			memcpy_user ( fbcon->start, offset, picture->start,
231
-				      picture_offset, row_len );
232
-
233
-		} else {
234
-
235
-			/* Otherwise, draw left and right margins */
236
-			memcpy_user ( fbcon->start, offset, picture->start,
237
-				      picture_offset, left_len );
238
-			memcpy_user ( fbcon->start, ( offset + right_offset ),
239
-				      picture->start,
240
-				      ( picture_offset + right_offset ),
241
-				      right_len );
242
-		}
243
-		offset += fbcon->pixel->stride;
244
-		picture_offset += picture->pixel.stride;
245
-	}
246
-}
247
-
248
-/**
249
- * Redraw characters
250
- *
251
- * @v fbcon		Frame buffer console
252
- */
253
-static void fbcon_redraw_characters ( struct fbcon *fbcon ) {
218
+static void fbcon_redraw ( struct fbcon *fbcon ) {
254
 	struct fbcon_text_cell cell;
219
 	struct fbcon_text_cell cell;
255
 	size_t offset = 0;
220
 	size_t offset = 0;
256
 	unsigned int xpos;
221
 	unsigned int xpos;
261
 		for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) {
226
 		for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) {
262
 			copy_from_user ( &cell, fbcon->text.start, offset,
227
 			copy_from_user ( &cell, fbcon->text.start, offset,
263
 					 sizeof ( cell ) );
228
 					 sizeof ( cell ) );
264
-			fbcon_draw_character ( fbcon, &cell, xpos, ypos );
229
+			fbcon_draw ( fbcon, &cell, xpos, ypos );
265
 			offset += sizeof ( cell );
230
 			offset += sizeof ( cell );
266
 		}
231
 		}
267
 	}
232
 	}
268
 }
233
 }
269
 
234
 
270
-/**
271
- * Redraw screen
272
- *
273
- * @v fbcon		Frame buffer console
274
- */
275
-static void fbcon_redraw ( struct fbcon *fbcon ) {
276
-
277
-	/* Redraw margins */
278
-	fbcon_redraw_margins ( fbcon );
279
-
280
-	/* Redraw characters */
281
-	fbcon_redraw_characters ( fbcon );
282
-}
283
-
284
-/**
285
- * Clear portion of screen
286
- *
287
- * @v fbcon		Frame buffer console
288
- * @v ypos		Starting Y position
289
- */
290
-static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
291
-	struct fbcon_text_cell cell = {
292
-		.foreground = fbcon->foreground,
293
-		.background = fbcon->background,
294
-		.character = ' ',
295
-	};
296
-	size_t offset;
297
-	unsigned int xpos;
298
-
299
-	/* Clear stored character array */
300
-	for ( ; ypos < fbcon->character.height ; ypos++ ) {
301
-		offset = ( ypos * fbcon->character.width * sizeof ( cell ) );
302
-		for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) {
303
-			copy_to_user ( fbcon->text.start, offset, &cell,
304
-				       sizeof ( cell ) );
305
-			offset += sizeof ( cell );
306
-		}
307
-	}
308
-
309
-	/* Redraw screen */
310
-	fbcon_redraw ( fbcon );
311
-}
312
-
313
 /**
235
 /**
314
  * Scroll screen
236
  * Scroll screen
315
  *
237
  *
329
 
251
 
330
 	/* Update cursor position */
252
 	/* Update cursor position */
331
 	fbcon->ypos--;
253
 	fbcon->ypos--;
254
+
255
+	/* Redraw all characters */
256
+	fbcon_redraw ( fbcon );
332
 }
257
 }
333
 
258
 
334
 /**
259
 /**
349
 		cell.foreground = ( ( fbcon->background == FBCON_TRANSPARENT ) ?
274
 		cell.foreground = ( ( fbcon->background == FBCON_TRANSPARENT ) ?
350
 				    0 : fbcon->background );
275
 				    0 : fbcon->background );
351
 	}
276
 	}
352
-	fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
277
+	fbcon_draw ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
353
 }
278
 }
354
 
279
 
355
 /**
280
 /**
391
 	/* We assume that we always clear the whole screen */
316
 	/* We assume that we always clear the whole screen */
392
 	assert ( params[0] == ANSIESC_ED_ALL );
317
 	assert ( params[0] == ANSIESC_ED_ALL );
393
 
318
 
394
-	/* Clear screen */
319
+	/* Clear character array */
395
 	fbcon_clear ( fbcon, 0 );
320
 	fbcon_clear ( fbcon, 0 );
396
 
321
 
322
+	/* Redraw all characters */
323
+	fbcon_redraw ( fbcon );
324
+
397
 	/* Reset cursor position */
325
 	/* Reset cursor position */
398
 	fbcon->xpos = 0;
326
 	fbcon->xpos = 0;
399
 	fbcon->ypos = 0;
327
 	fbcon->ypos = 0;
541
 		cell.foreground = ( fbcon->foreground | fbcon->bold );
469
 		cell.foreground = ( fbcon->foreground | fbcon->bold );
542
 		cell.background = fbcon->background;
470
 		cell.background = fbcon->background;
543
 		cell.character = character;
471
 		cell.character = character;
544
-		fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos);
545
-		fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
472
+		fbcon_store ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
473
+		fbcon_draw ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
546
 
474
 
547
 		/* Advance cursor */
475
 		/* Advance cursor */
548
 		fbcon->xpos++;
476
 		fbcon->xpos++;
561
 	fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
489
 	fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
562
 }
490
 }
563
 
491
 
564
-/**
565
- * Calculate character geometry from pixel geometry
566
- *
567
- * @v pixel		Pixel geometry
568
- * @v character		Character geometry to fill in
569
- */
570
-static void fbcon_char_geometry ( const struct fbcon_geometry *pixel,
571
-				  struct fbcon_geometry *character ) {
572
-
573
-	character->width = ( pixel->width / FBCON_CHAR_WIDTH );
574
-	character->height = ( pixel->height / FBCON_CHAR_HEIGHT );
575
-	character->len = ( pixel->len * FBCON_CHAR_WIDTH );
576
-	character->stride = ( pixel->stride * FBCON_CHAR_HEIGHT );
577
-}
578
-
579
-/**
580
- * Calculate margins from pixel geometry
581
- *
582
- * @v pixel		Pixel geometry
583
- * @v margin		Margins to fill in
584
- */
585
-static void fbcon_margin ( const struct fbcon_geometry *pixel,
586
-			   struct fbcon_margin *margin ) {
587
-	unsigned int xgap;
588
-	unsigned int ygap;
589
-
590
-	xgap = ( pixel->width % FBCON_CHAR_WIDTH );
591
-	ygap = ( pixel->height % FBCON_CHAR_HEIGHT );
592
-	margin->left = ( xgap / 2 );
593
-	margin->top = ( ygap / 2 );
594
-	margin->right = ( pixel->width - ( xgap - margin->left ) );
595
-	margin->bottom = ( pixel->height - ( ygap - margin->top ) );
596
-}
597
-
598
-/**
599
- * Align to first indented boundary
600
- *
601
- * @v value		Original value
602
- * @v blocksize		Block size
603
- * @v indent		Indent
604
- * @v max		Maximum allowed value
605
- * @ret value		Aligned value
606
- */
607
-static unsigned int fbcon_align ( unsigned int value, unsigned int blocksize,
608
-				  unsigned int indent, unsigned int max ) {
609
-	unsigned int overhang;
610
-
611
-	/* Special case: 0 is always a boundary regardless of the indent */
612
-	if ( value == 0 )
613
-		return value;
614
-
615
-	/* Special case: first boundary is the indent */
616
-	if ( value < indent )
617
-		return indent;
618
-
619
-	/* Round up to next indented boundary */
620
-	overhang = ( ( value - indent ) % blocksize );
621
-	value = ( value + ( ( blocksize - overhang ) % blocksize ) );
622
-
623
-	/* Limit to maximum value */
624
-	if ( value > max )
625
-		value = max;
626
-
627
-	return value;
628
-}
629
-
630
 /**
492
 /**
631
  * Initialise background picture
493
  * Initialise background picture
632
  *
494
  *
636
  */
498
  */
637
 static int fbcon_picture_init ( struct fbcon *fbcon,
499
 static int fbcon_picture_init ( struct fbcon *fbcon,
638
 				struct pixel_buffer *pixbuf ) {
500
 				struct pixel_buffer *pixbuf ) {
501
+	struct fbcon_geometry *pixel = fbcon->pixel;
639
 	struct fbcon_picture *picture = &fbcon->picture;
502
 	struct fbcon_picture *picture = &fbcon->picture;
640
-	size_t pixel_len = fbcon->pixel->len;
641
 	size_t len;
503
 	size_t len;
504
+	size_t pixbuf_stride;
505
+	size_t indent;
506
+	size_t pixbuf_indent;
642
 	size_t offset;
507
 	size_t offset;
643
 	size_t pixbuf_offset;
508
 	size_t pixbuf_offset;
644
 	uint32_t rgb;
509
 	uint32_t rgb;
645
 	uint32_t raw;
510
 	uint32_t raw;
646
 	unsigned int x;
511
 	unsigned int x;
647
 	unsigned int y;
512
 	unsigned int y;
513
+	unsigned int width;
514
+	unsigned int height;
515
+	int xgap;
516
+	int ygap;
648
 	int rc;
517
 	int rc;
649
 
518
 
650
-	/* Calculate pixel geometry */
651
-	picture->pixel.width = fbcon_align ( pixbuf->width, FBCON_CHAR_WIDTH,
652
-					     fbcon->margin.left,
653
-					     fbcon->pixel->width );
654
-	picture->pixel.height = fbcon_align ( pixbuf->height, FBCON_CHAR_HEIGHT,
655
-					      fbcon->margin.top,
656
-					      fbcon->pixel->height );
657
-	picture->pixel.len = pixel_len;
658
-	picture->pixel.stride = ( picture->pixel.width * picture->pixel.len );
659
-
660
-	/* Calculate character geometry */
661
-	fbcon_char_geometry ( &picture->pixel, &picture->character );
662
-
663
-	/* Calculate margins */
664
-	memcpy ( &picture->margin, &fbcon->margin, sizeof ( picture->margin ) );
665
-	if ( picture->margin.left > picture->pixel.width )
666
-		picture->margin.left = picture->pixel.width;
667
-	if ( picture->margin.top > picture->pixel.height )
668
-		picture->margin.top = picture->pixel.height;
669
-	if ( picture->margin.right > picture->pixel.width )
670
-		picture->margin.right = picture->pixel.width;
671
-	if ( picture->margin.bottom > picture->pixel.height )
672
-		picture->margin.bottom = picture->pixel.height;
673
-	picture->indent = ( ( picture->margin.top * picture->pixel.stride ) +
674
-			    ( picture->margin.left * picture->pixel.len ) );
675
-	DBGC ( fbcon, "FBCON %p picture is pixel %dx%d, char %dx%d at "
676
-	       "[%d-%d),[%d-%d)\n", fbcon, picture->pixel.width,
677
-	       picture->pixel.height, picture->character.width,
678
-	       picture->character.height, picture->margin.left,
679
-	       picture->margin.right, picture->margin.top,
680
-	       picture->margin.bottom );
681
-
682
 	/* Allocate buffer */
519
 	/* Allocate buffer */
683
-	len = ( picture->pixel.width * picture->pixel.height *
684
-		picture->pixel.len );
520
+	len = ( pixel->height * pixel->stride );
685
 	picture->start = umalloc ( len );
521
 	picture->start = umalloc ( len );
686
 	if ( ! picture->start ) {
522
 	if ( ! picture->start ) {
687
 		DBGC ( fbcon, "FBCON %p could not allocate %zd bytes for "
523
 		DBGC ( fbcon, "FBCON %p could not allocate %zd bytes for "
690
 		goto err_umalloc;
526
 		goto err_umalloc;
691
 	}
527
 	}
692
 
528
 
529
+	/* Centre picture on console */
530
+	pixbuf_stride = ( pixbuf->width * sizeof ( rgb ) );
531
+	xgap = ( ( ( int ) ( pixel->width - pixbuf->width ) ) / 2 );
532
+	ygap = ( ( ( int ) ( pixel->height - pixbuf->height ) ) / 2 );
533
+	indent = ( ( ( ( ygap >= 0 ) ? ygap : 0 ) * pixel->stride ) +
534
+		   ( ( ( xgap >= 0 ) ? xgap : 0 ) * pixel->len ) );
535
+	pixbuf_indent =	( ( ( ( ygap < 0 ) ? -ygap : 0 ) * pixbuf_stride ) +
536
+			  ( ( ( xgap < 0 ) ? -xgap : 0 ) * sizeof ( rgb ) ) );
537
+	width = pixbuf->width;
538
+	if ( width > pixel->width )
539
+		width = pixel->width;
540
+	height = pixbuf->height;
541
+	if ( height > pixel->height )
542
+		height = pixel->height;
543
+	DBGC ( fbcon, "FBCON %p picture is pixel %dx%d at [%d,%d),[%d,%d)\n",
544
+	       fbcon, width, height, xgap, ( xgap + pixbuf->width ), ygap,
545
+	       ( ygap + pixbuf->height ) );
546
+
693
 	/* Convert to frame buffer raw format */
547
 	/* Convert to frame buffer raw format */
694
 	memset_user ( picture->start, 0, 0, len );
548
 	memset_user ( picture->start, 0, 0, len );
695
-	pixbuf_offset = 0;
696
-	for ( y = 0 ; ( y < pixbuf->height ) &&
697
-		      ( y < picture->pixel.height ) ; y++ ) {
698
-		offset = ( y * picture->pixel.stride );
699
-		pixbuf_offset = ( y * pixbuf->width * sizeof ( rgb ) );
700
-		for ( x = 0 ; ( x < pixbuf->width ) &&
701
-			      ( x < picture->pixel.width ) ; x++ ) {
549
+	for ( y = 0 ; y < height ; y++ ) {
550
+		offset = ( indent + ( y * pixel->stride ) );
551
+		pixbuf_offset = ( pixbuf_indent + ( y * pixbuf_stride ) );
552
+		for ( x = 0 ; x < width ; x++ ) {
702
 			copy_from_user ( &rgb, pixbuf->data, pixbuf_offset,
553
 			copy_from_user ( &rgb, pixbuf->data, pixbuf_offset,
703
 					 sizeof ( rgb ) );
554
 					 sizeof ( rgb ) );
704
 			raw = fbcon_colour ( fbcon, rgb );
555
 			raw = fbcon_colour ( fbcon, rgb );
705
-			copy_to_user ( picture->start, offset, &raw, pixel_len);
706
-			offset += pixel_len;
556
+			copy_to_user ( picture->start, offset, &raw,
557
+				       pixel->len );
558
+			offset += pixel->len;
707
 			pixbuf_offset += sizeof ( rgb );
559
 			pixbuf_offset += sizeof ( rgb );
708
 		}
560
 		}
709
 	}
561
 	}
731
 		 struct fbcon_colour_map *map,
583
 		 struct fbcon_colour_map *map,
732
 		 struct fbcon_font *font,
584
 		 struct fbcon_font *font,
733
 		 struct pixel_buffer *pixbuf ) {
585
 		 struct pixel_buffer *pixbuf ) {
586
+	unsigned int xgap;
587
+	unsigned int ygap;
734
 	int rc;
588
 	int rc;
735
 
589
 
736
 	/* Initialise data structure */
590
 	/* Initialise data structure */
750
 	       user_to_phys ( fbcon->start, fbcon->len ) );
604
 	       user_to_phys ( fbcon->start, fbcon->len ) );
751
 
605
 
752
 	/* Derive character geometry from pixel geometry */
606
 	/* Derive character geometry from pixel geometry */
753
-	fbcon_char_geometry ( pixel, &fbcon->character );
754
-	fbcon_margin ( pixel, &fbcon->margin );
607
+	fbcon->character.width = ( pixel->width / FBCON_CHAR_WIDTH );
608
+	fbcon->character.height = ( pixel->height / FBCON_CHAR_HEIGHT );
609
+	fbcon->character.len = ( pixel->len * FBCON_CHAR_WIDTH );
610
+	fbcon->character.stride = ( pixel->stride * FBCON_CHAR_HEIGHT );
611
+
612
+	/* Calculate margin */
613
+	xgap = ( pixel->width % FBCON_CHAR_WIDTH );
614
+	ygap = ( pixel->height % FBCON_CHAR_HEIGHT );
615
+	fbcon->margin.left = ( xgap / 2 );
616
+	fbcon->margin.top = ( ygap / 2 );
617
+	fbcon->margin.right = ( xgap - fbcon->margin.left );
618
+	fbcon->margin.bottom = ( ygap - fbcon->margin.top );
755
 	fbcon->indent = ( ( fbcon->margin.top * pixel->stride ) +
619
 	fbcon->indent = ( ( fbcon->margin.top * pixel->stride ) +
756
 			  ( fbcon->margin.left * pixel->len ) );
620
 			  ( fbcon->margin.left * pixel->len ) );
757
 	DBGC ( fbcon, "FBCON %p is pixel %dx%d, char %dx%d at "
621
 	DBGC ( fbcon, "FBCON %p is pixel %dx%d, char %dx%d at "
758
 	       "[%d-%d),[%d-%d)\n", fbcon, fbcon->pixel->width,
622
 	       "[%d-%d),[%d-%d)\n", fbcon, fbcon->pixel->width,
759
 	       fbcon->pixel->height, fbcon->character.width,
623
 	       fbcon->pixel->height, fbcon->character.width,
760
-	       fbcon->character.height, fbcon->margin.left, fbcon->margin.right,
761
-	       fbcon->margin.top, fbcon->margin.bottom );
624
+	       fbcon->character.height, fbcon->margin.left,
625
+	       ( fbcon->pixel->width - fbcon->margin.right ),
626
+	       fbcon->margin.top,
627
+	       ( fbcon->pixel->height - fbcon->margin.bottom ) );
762
 
628
 
763
 	/* Set default colours */
629
 	/* Set default colours */
764
 	fbcon_set_default_foreground ( fbcon );
630
 	fbcon_set_default_foreground ( fbcon );
765
 	fbcon_set_default_background ( fbcon );
631
 	fbcon_set_default_background ( fbcon );
766
 
632
 
767
-	/* Allocate stored character array */
633
+	/* Allocate and initialise stored character array */
768
 	fbcon->text.start = umalloc ( fbcon->character.width *
634
 	fbcon->text.start = umalloc ( fbcon->character.width *
769
 				      fbcon->character.height *
635
 				      fbcon->character.height *
770
 				      sizeof ( struct fbcon_text_cell ) );
636
 				      sizeof ( struct fbcon_text_cell ) );
772
 		rc = -ENOMEM;
638
 		rc = -ENOMEM;
773
 		goto err_text;
639
 		goto err_text;
774
 	}
640
 	}
641
+	fbcon_clear ( fbcon, 0 );
642
+
643
+	/* Set framebuffer to all black (including margins) */
644
+	memset_user ( fbcon->start, 0, 0, fbcon->len );
775
 
645
 
776
 	/* Generate pixel buffer from background image, if applicable */
646
 	/* Generate pixel buffer from background image, if applicable */
777
 	if ( pixbuf && ( ( rc = fbcon_picture_init ( fbcon, pixbuf ) ) != 0 ) )
647
 	if ( pixbuf && ( ( rc = fbcon_picture_init ( fbcon, pixbuf ) ) != 0 ) )
778
 		goto err_picture;
648
 		goto err_picture;
779
 
649
 
780
-	/* Clear screen */
781
-	fbcon_clear ( fbcon, 0 );
650
+	/* Draw background picture (including margins), if applicable */
651
+	if ( fbcon->picture.start ) {
652
+		memcpy_user ( fbcon->start, 0, fbcon->picture.start, 0,
653
+			      fbcon->len );
654
+	}
782
 
655
 
783
 	/* Update console width and height */
656
 	/* Update console width and height */
784
 	console_set_size ( fbcon->character.width, fbcon->character.height );
657
 	console_set_size ( fbcon->character.width, fbcon->character.height );

+ 0
- 8
src/include/ipxe/fbcon.h View File

103
 struct fbcon_picture {
103
 struct fbcon_picture {
104
 	/** Start address */
104
 	/** Start address */
105
 	userptr_t start;
105
 	userptr_t start;
106
-	/** Pixel geometry */
107
-	struct fbcon_geometry pixel;
108
-	/** Character geometry */
109
-	struct fbcon_geometry character;
110
-	/** Margin */
111
-	struct fbcon_margin margin;
112
-	/** Indent to first character (in bytes) */
113
-	size_t indent;
114
 };
106
 };
115
 
107
 
116
 /** A frame buffer console */
108
 /** A frame buffer console */

Loading…
Cancel
Save