|  | @@ -98,6 +98,32 @@ static void fbcon_set_default_background ( struct fbcon *fbcon ) {
 | 
		
	
		
			
			| 98 | 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 | 128 |   * Store character at specified position
 | 
		
	
		
			
			| 103 | 129 |   *
 | 
		
	
	
		
			
			|  | @@ -106,9 +132,8 @@ static void fbcon_set_default_background ( struct fbcon *fbcon ) {
 | 
		
	
		
			
			| 106 | 132 |   * @v xpos		X position
 | 
		
	
		
			
			| 107 | 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 | 137 |  	size_t offset;
 | 
		
	
		
			
			| 113 | 138 |  
 | 
		
	
		
			
			| 114 | 139 |  	/* Store cell */
 | 
		
	
	
		
			
			|  | @@ -125,14 +150,9 @@ static void fbcon_store_character ( struct fbcon *fbcon,
 | 
		
	
		
			
			| 125 | 150 |   * @v xpos		X position
 | 
		
	
		
			
			| 126 | 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 | 155 |  	struct fbcon_font_glyph glyph;
 | 
		
	
		
			
			| 133 |  | -	userptr_t picture_start;
 | 
		
	
		
			
			| 134 |  | -	size_t picture_offset;
 | 
		
	
		
			
			| 135 |  | -	size_t picture_stride;
 | 
		
	
		
			
			| 136 | 156 |  	size_t offset;
 | 
		
	
		
			
			| 137 | 157 |  	size_t pixel_len;
 | 
		
	
		
			
			| 138 | 158 |  	size_t skip_len;
 | 
		
	
	
		
			
			|  | @@ -154,30 +174,23 @@ static void fbcon_draw_character ( struct fbcon *fbcon,
 | 
		
	
		
			
			| 154 | 174 |  	pixel_len = fbcon->pixel->len;
 | 
		
	
		
			
			| 155 | 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 | 177 |  	/* Check for transparent background colour */
 | 
		
	
		
			
			| 173 | 178 |  	transparent = ( cell->background == FBCON_TRANSPARENT );
 | 
		
	
		
			
			| 174 | 179 |  
 | 
		
	
		
			
			| 175 | 180 |  	/* Draw character rows */
 | 
		
	
		
			
			| 176 | 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 | 195 |  		/* Draw character row */
 | 
		
	
		
			
			| 183 | 196 |  		for ( column = FBCON_CHAR_WIDTH, bitmask = glyph.bitmask[row] ;
 | 
		
	
	
		
			
			|  | @@ -194,63 +207,15 @@ static void fbcon_draw_character ( struct fbcon *fbcon,
 | 
		
	
		
			
			| 194 | 207 |  
 | 
		
	
		
			
			| 195 | 208 |  		/* Move to next row */
 | 
		
	
		
			
			| 196 | 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 | 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 | 219 |  	struct fbcon_text_cell cell;
 | 
		
	
		
			
			| 255 | 220 |  	size_t offset = 0;
 | 
		
	
		
			
			| 256 | 221 |  	unsigned int xpos;
 | 
		
	
	
		
			
			|  | @@ -261,55 +226,12 @@ static void fbcon_redraw_characters ( struct fbcon *fbcon ) {
 | 
		
	
		
			
			| 261 | 226 |  		for ( xpos = 0 ; xpos < fbcon->character.width ; xpos++ ) {
 | 
		
	
		
			
			| 262 | 227 |  			copy_from_user ( &cell, fbcon->text.start, offset,
 | 
		
	
		
			
			| 263 | 228 |  					 sizeof ( cell ) );
 | 
		
	
		
			
			| 264 |  | -			fbcon_draw_character ( fbcon, &cell, xpos, ypos );
 | 
		
	
		
			
			|  | 229 | +			fbcon_draw ( fbcon, &cell, xpos, ypos );
 | 
		
	
		
			
			| 265 | 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 | 236 |   * Scroll screen
 | 
		
	
		
			
			| 315 | 237 |   *
 | 
		
	
	
		
			
			|  | @@ -329,6 +251,9 @@ static void fbcon_scroll ( struct fbcon *fbcon ) {
 | 
		
	
		
			
			| 329 | 251 |  
 | 
		
	
		
			
			| 330 | 252 |  	/* Update cursor position */
 | 
		
	
		
			
			| 331 | 253 |  	fbcon->ypos--;
 | 
		
	
		
			
			|  | 254 | +
 | 
		
	
		
			
			|  | 255 | +	/* Redraw all characters */
 | 
		
	
		
			
			|  | 256 | +	fbcon_redraw ( fbcon );
 | 
		
	
		
			
			| 332 | 257 |  }
 | 
		
	
		
			
			| 333 | 258 |  
 | 
		
	
		
			
			| 334 | 259 |  /**
 | 
		
	
	
		
			
			|  | @@ -349,7 +274,7 @@ static void fbcon_draw_cursor ( struct fbcon *fbcon, int show_cursor ) {
 | 
		
	
		
			
			| 349 | 274 |  		cell.foreground = ( ( fbcon->background == FBCON_TRANSPARENT ) ?
 | 
		
	
		
			
			| 350 | 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,9 +316,12 @@ static void fbcon_handle_ed ( struct ansiesc_context *ctx,
 | 
		
	
		
			
			| 391 | 316 |  	/* We assume that we always clear the whole screen */
 | 
		
	
		
			
			| 392 | 317 |  	assert ( params[0] == ANSIESC_ED_ALL );
 | 
		
	
		
			
			| 393 | 318 |  
 | 
		
	
		
			
			| 394 |  | -	/* Clear screen */
 | 
		
	
		
			
			|  | 319 | +	/* Clear character array */
 | 
		
	
		
			
			| 395 | 320 |  	fbcon_clear ( fbcon, 0 );
 | 
		
	
		
			
			| 396 | 321 |  
 | 
		
	
		
			
			|  | 322 | +	/* Redraw all characters */
 | 
		
	
		
			
			|  | 323 | +	fbcon_redraw ( fbcon );
 | 
		
	
		
			
			|  | 324 | +
 | 
		
	
		
			
			| 397 | 325 |  	/* Reset cursor position */
 | 
		
	
		
			
			| 398 | 326 |  	fbcon->xpos = 0;
 | 
		
	
		
			
			| 399 | 327 |  	fbcon->ypos = 0;
 | 
		
	
	
		
			
			|  | @@ -541,8 +469,8 @@ void fbcon_putchar ( struct fbcon *fbcon, int character ) {
 | 
		
	
		
			
			| 541 | 469 |  		cell.foreground = ( fbcon->foreground | fbcon->bold );
 | 
		
	
		
			
			| 542 | 470 |  		cell.background = fbcon->background;
 | 
		
	
		
			
			| 543 | 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 | 475 |  		/* Advance cursor */
 | 
		
	
		
			
			| 548 | 476 |  		fbcon->xpos++;
 | 
		
	
	
		
			
			|  | @@ -561,72 +489,6 @@ void fbcon_putchar ( struct fbcon *fbcon, int character ) {
 | 
		
	
		
			
			| 561 | 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 | 493 |   * Initialise background picture
 | 
		
	
		
			
			| 632 | 494 |   *
 | 
		
	
	
		
			
			|  | @@ -636,52 +498,26 @@ static unsigned int fbcon_align ( unsigned int value, unsigned int blocksize,
 | 
		
	
		
			
			| 636 | 498 |   */
 | 
		
	
		
			
			| 637 | 499 |  static int fbcon_picture_init ( struct fbcon *fbcon,
 | 
		
	
		
			
			| 638 | 500 |  				struct pixel_buffer *pixbuf ) {
 | 
		
	
		
			
			|  | 501 | +	struct fbcon_geometry *pixel = fbcon->pixel;
 | 
		
	
		
			
			| 639 | 502 |  	struct fbcon_picture *picture = &fbcon->picture;
 | 
		
	
		
			
			| 640 |  | -	size_t pixel_len = fbcon->pixel->len;
 | 
		
	
		
			
			| 641 | 503 |  	size_t len;
 | 
		
	
		
			
			|  | 504 | +	size_t pixbuf_stride;
 | 
		
	
		
			
			|  | 505 | +	size_t indent;
 | 
		
	
		
			
			|  | 506 | +	size_t pixbuf_indent;
 | 
		
	
		
			
			| 642 | 507 |  	size_t offset;
 | 
		
	
		
			
			| 643 | 508 |  	size_t pixbuf_offset;
 | 
		
	
		
			
			| 644 | 509 |  	uint32_t rgb;
 | 
		
	
		
			
			| 645 | 510 |  	uint32_t raw;
 | 
		
	
		
			
			| 646 | 511 |  	unsigned int x;
 | 
		
	
		
			
			| 647 | 512 |  	unsigned int y;
 | 
		
	
		
			
			|  | 513 | +	unsigned int width;
 | 
		
	
		
			
			|  | 514 | +	unsigned int height;
 | 
		
	
		
			
			|  | 515 | +	int xgap;
 | 
		
	
		
			
			|  | 516 | +	int ygap;
 | 
		
	
		
			
			| 648 | 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 | 519 |  	/* Allocate buffer */
 | 
		
	
		
			
			| 683 |  | -	len = ( picture->pixel.width * picture->pixel.height *
 | 
		
	
		
			
			| 684 |  | -		picture->pixel.len );
 | 
		
	
		
			
			|  | 520 | +	len = ( pixel->height * pixel->stride );
 | 
		
	
		
			
			| 685 | 521 |  	picture->start = umalloc ( len );
 | 
		
	
		
			
			| 686 | 522 |  	if ( ! picture->start ) {
 | 
		
	
		
			
			| 687 | 523 |  		DBGC ( fbcon, "FBCON %p could not allocate %zd bytes for "
 | 
		
	
	
		
			
			|  | @@ -690,20 +526,36 @@ static int fbcon_picture_init ( struct fbcon *fbcon,
 | 
		
	
		
			
			| 690 | 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 | 547 |  	/* Convert to frame buffer raw format */
 | 
		
	
		
			
			| 694 | 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 | 553 |  			copy_from_user ( &rgb, pixbuf->data, pixbuf_offset,
 | 
		
	
		
			
			| 703 | 554 |  					 sizeof ( rgb ) );
 | 
		
	
		
			
			| 704 | 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 | 559 |  			pixbuf_offset += sizeof ( rgb );
 | 
		
	
		
			
			| 708 | 560 |  		}
 | 
		
	
		
			
			| 709 | 561 |  	}
 | 
		
	
	
		
			
			|  | @@ -731,6 +583,8 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
 | 
		
	
		
			
			| 731 | 583 |  		 struct fbcon_colour_map *map,
 | 
		
	
		
			
			| 732 | 584 |  		 struct fbcon_font *font,
 | 
		
	
		
			
			| 733 | 585 |  		 struct pixel_buffer *pixbuf ) {
 | 
		
	
		
			
			|  | 586 | +	unsigned int xgap;
 | 
		
	
		
			
			|  | 587 | +	unsigned int ygap;
 | 
		
	
		
			
			| 734 | 588 |  	int rc;
 | 
		
	
		
			
			| 735 | 589 |  
 | 
		
	
		
			
			| 736 | 590 |  	/* Initialise data structure */
 | 
		
	
	
		
			
			|  | @@ -750,21 +604,33 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
 | 
		
	
		
			
			| 750 | 604 |  	       user_to_phys ( fbcon->start, fbcon->len ) );
 | 
		
	
		
			
			| 751 | 605 |  
 | 
		
	
		
			
			| 752 | 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 | 619 |  	fbcon->indent = ( ( fbcon->margin.top * pixel->stride ) +
 | 
		
	
		
			
			| 756 | 620 |  			  ( fbcon->margin.left * pixel->len ) );
 | 
		
	
		
			
			| 757 | 621 |  	DBGC ( fbcon, "FBCON %p is pixel %dx%d, char %dx%d at "
 | 
		
	
		
			
			| 758 | 622 |  	       "[%d-%d),[%d-%d)\n", fbcon, fbcon->pixel->width,
 | 
		
	
		
			
			| 759 | 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 | 629 |  	/* Set default colours */
 | 
		
	
		
			
			| 764 | 630 |  	fbcon_set_default_foreground ( fbcon );
 | 
		
	
		
			
			| 765 | 631 |  	fbcon_set_default_background ( fbcon );
 | 
		
	
		
			
			| 766 | 632 |  
 | 
		
	
		
			
			| 767 |  | -	/* Allocate stored character array */
 | 
		
	
		
			
			|  | 633 | +	/* Allocate and initialise stored character array */
 | 
		
	
		
			
			| 768 | 634 |  	fbcon->text.start = umalloc ( fbcon->character.width *
 | 
		
	
		
			
			| 769 | 635 |  				      fbcon->character.height *
 | 
		
	
		
			
			| 770 | 636 |  				      sizeof ( struct fbcon_text_cell ) );
 | 
		
	
	
		
			
			|  | @@ -772,13 +638,20 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
 | 
		
	
		
			
			| 772 | 638 |  		rc = -ENOMEM;
 | 
		
	
		
			
			| 773 | 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 | 646 |  	/* Generate pixel buffer from background image, if applicable */
 | 
		
	
		
			
			| 777 | 647 |  	if ( pixbuf && ( ( rc = fbcon_picture_init ( fbcon, pixbuf ) ) != 0 ) )
 | 
		
	
		
			
			| 778 | 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 | 656 |  	/* Update console width and height */
 | 
		
	
		
			
			| 784 | 657 |  	console_set_size ( fbcon->character.width, fbcon->character.height );
 |