|
@@ -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 );
|