~ubuntu-branches/debian/stretch/grub2/stretch

« back to all changes in this revision

Viewing changes to video/fb/video_fb.c

Tags: upstream-1.98+20100705
ImportĀ upstreamĀ versionĀ 1.98+20100705

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <grub/fbutil.h>
26
26
#include <grub/bitmap.h>
27
27
 
28
 
static struct grub_video_fbrender_target *render_target;
29
 
struct grub_video_palette_data *palette;
30
 
static unsigned int palette_size;
 
28
static struct
 
29
{
 
30
  struct grub_video_fbrender_target *render_target;
 
31
  struct grub_video_fbrender_target *front_target;
 
32
  struct grub_video_fbrender_target *back_target;
 
33
  struct grub_video_palette_data *palette;
 
34
  unsigned int palette_size;
 
35
  /* For page flipping strategy.  */
 
36
  int displayed_page;           /* The page # that is the front buffer.  */
 
37
  int render_page;              /* The page # that is the back buffer.  */
 
38
  grub_video_fb_set_page_t set_page;
 
39
  char *offscreen_buffer;
 
40
  grub_video_fb_doublebuf_update_screen_t update_screen;
 
41
} framebuffer;
31
42
 
32
43
/* Specify "standard" VGA palette, some video cards may
33
44
   need this and this will also be used when using RGB modes.  */
56
67
grub_err_t
57
68
grub_video_fb_init (void)
58
69
{
59
 
  grub_free (palette);
60
 
  render_target = 0;
61
 
  palette = 0;
62
 
  palette_size = 0;
 
70
  grub_free (framebuffer.palette);
 
71
  framebuffer.render_target = 0;
 
72
  framebuffer.front_target = 0;
 
73
  framebuffer.back_target = 0;
 
74
  framebuffer.palette = 0;
 
75
  framebuffer.palette_size = 0;
 
76
  framebuffer.set_page = 0;
63
77
  return GRUB_ERR_NONE;
64
78
}
65
79
 
68
82
{
69
83
  /* TODO: destroy render targets.  */
70
84
 
71
 
  grub_free (palette);
72
 
  render_target = 0;
73
 
  palette = 0;
74
 
  palette_size = 0;
 
85
  grub_free (framebuffer.offscreen_buffer);
 
86
  grub_free (framebuffer.palette);
 
87
  framebuffer.render_target = 0;
 
88
  framebuffer.front_target = 0;
 
89
  framebuffer.back_target = 0;
 
90
  framebuffer.palette = 0;
 
91
  framebuffer.palette_size = 0;
 
92
  framebuffer.set_page = 0;
 
93
  framebuffer.offscreen_buffer = 0;
75
94
  return GRUB_ERR_NONE;
76
95
}
77
96
 
79
98
grub_video_fb_get_info (struct grub_video_mode_info *mode_info)
80
99
{
81
100
  /* Copy mode info from active render target.  */
82
 
  grub_memcpy (mode_info, &render_target->mode_info,
 
101
  grub_memcpy (mode_info, &framebuffer.render_target->mode_info,
83
102
               sizeof (struct grub_video_mode_info));
84
103
 
85
104
  return GRUB_ERR_NONE;
92
111
  unsigned int i;
93
112
 
94
113
  /* Assume that we know everything from index color palette.  */
95
 
  for (i = 0; (i < count) && ((i + start) < palette_size); i++)
96
 
    palette_data[i] = palette[start + i];
 
114
  for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++)
 
115
    palette_data[i] = framebuffer.palette[start + i];
97
116
 
98
117
  return GRUB_ERR_NONE;
99
118
}
103
122
                           struct grub_video_palette_data *palette_data)
104
123
{
105
124
  unsigned i;
106
 
  if (start + count > palette_size)
 
125
  if (start + count > framebuffer.palette_size)
107
126
    {
108
 
      palette_size = start + count;
109
 
      palette = grub_realloc (palette, sizeof (palette[0]) * palette_size);
110
 
      if (!palette)
 
127
      framebuffer.palette_size = start + count;
 
128
      framebuffer.palette = grub_realloc (framebuffer.palette,
 
129
                                          sizeof (framebuffer.palette[0])
 
130
                                          * framebuffer.palette_size);
 
131
      if (!framebuffer.palette)
111
132
        {
112
133
          grub_video_fb_fini ();
113
134
          return grub_errno;
114
135
        }
115
136
    }
116
 
  for (i = 0; (i < count) && ((i + start) < palette_size); i++)
117
 
    palette[start + i] = palette_data[i];
 
137
  for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++)
 
138
    framebuffer.palette[start + i] = palette_data[i];
118
139
  return GRUB_ERR_NONE;
119
140
}
120
141
 
124
145
{
125
146
  /* Make sure viewport is withing screen dimensions.  If viewport was set
126
147
     to be out of the region, mark its size as zero.  */
127
 
  if (x > render_target->mode_info.width)
 
148
  if (x > framebuffer.render_target->mode_info.width)
128
149
    {
129
150
      x = 0;
130
151
      width = 0;
131
152
    }
132
153
 
133
 
  if (y > render_target->mode_info.height)
 
154
  if (y > framebuffer.render_target->mode_info.height)
134
155
    {
135
156
      y = 0;
136
157
      height = 0;
137
158
    }
138
159
 
139
 
  if (x + width > render_target->mode_info.width)
140
 
    width = render_target->mode_info.width - x;
141
 
 
142
 
  if (y + height > render_target->mode_info.height)
143
 
    height = render_target->mode_info.height - y;
144
 
 
145
 
  render_target->viewport.x = x;
146
 
  render_target->viewport.y = y;
147
 
  render_target->viewport.width = width;
148
 
  render_target->viewport.height = height;
 
160
  if (x + width > framebuffer.render_target->mode_info.width)
 
161
    width = framebuffer.render_target->mode_info.width - x;
 
162
 
 
163
  if (y + height > framebuffer.render_target->mode_info.height)
 
164
    height = framebuffer.render_target->mode_info.height - y;
 
165
 
 
166
  framebuffer.render_target->viewport.x = x;
 
167
  framebuffer.render_target->viewport.y = y;
 
168
  framebuffer.render_target->viewport.width = width;
 
169
  framebuffer.render_target->viewport.height = height;
149
170
 
150
171
  return GRUB_ERR_NONE;
151
172
}
154
175
grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
155
176
                            unsigned int *width, unsigned int *height)
156
177
{
157
 
  if (x) *x = render_target->viewport.x;
158
 
  if (y) *y = render_target->viewport.y;
159
 
  if (width) *width = render_target->viewport.width;
160
 
  if (height) *height = render_target->viewport.height;
 
178
  if (x) *x = framebuffer.render_target->viewport.x;
 
179
  if (y) *y = framebuffer.render_target->viewport.y;
 
180
  if (width) *width = framebuffer.render_target->viewport.width;
 
181
  if (height) *height = framebuffer.render_target->viewport.height;
161
182
 
162
183
  return GRUB_ERR_NONE;
163
184
}
168
189
{
169
190
  /* TODO: implement color theme mapping code.  */
170
191
 
171
 
  if (color_name < palette_size)
 
192
  if (color_name < framebuffer.palette_size)
172
193
    {
173
 
      if ((render_target->mode_info.mode_type
 
194
      if ((framebuffer.render_target->mode_info.mode_type
174
195
           & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
175
196
        return color_name;
176
197
      else
177
198
        {
178
199
          grub_video_color_t color;
179
200
 
180
 
          color = grub_video_fb_map_rgb (palette[color_name].r,
181
 
                                         palette[color_name].g,
182
 
                                         palette[color_name].b);
 
201
          color = grub_video_fb_map_rgb (framebuffer.palette[color_name].r,
 
202
                                         framebuffer.palette[color_name].g,
 
203
                                         framebuffer.palette[color_name].b);
183
204
 
184
205
          return color;
185
206
        }
193
214
grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
194
215
                       grub_uint8_t blue)
195
216
{
196
 
  if ((render_target->mode_info.mode_type
 
217
  if ((framebuffer.render_target->mode_info.mode_type
197
218
       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
198
219
    {
199
220
      int minindex = 0;
203
224
      unsigned i;
204
225
 
205
226
      /* Find best matching color.  */
206
 
      for (i = 0; i < palette_size; i++)
 
227
      for (i = 0; i < framebuffer.palette_size; i++)
207
228
        {
208
 
          val = palette[i].r - red;
 
229
          val = framebuffer.palette[i].r - red;
209
230
          tmp = val * val;
210
 
          val = palette[i].g - green;
 
231
          val = framebuffer.palette[i].g - green;
211
232
          tmp += val * val;
212
 
          val = palette[i].b - blue;
 
233
          val = framebuffer.palette[i].b - blue;
213
234
          tmp += val * val;
214
235
 
215
236
          if (i == 0)
226
247
 
227
248
      return minindex;
228
249
    }
229
 
  else if ((render_target->mode_info.mode_type
 
250
  else if ((framebuffer.render_target->mode_info.mode_type
230
251
            & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
231
252
    {
232
 
       if (red == render_target->mode_info.fg_red
233
 
           && green == render_target->mode_info.fg_green
234
 
           && blue == render_target->mode_info.fg_blue)
 
253
       if (red == framebuffer.render_target->mode_info.fg_red
 
254
           && green == framebuffer.render_target->mode_info.fg_green
 
255
           && blue == framebuffer.render_target->mode_info.fg_blue)
235
256
         return 1;
236
257
       else
237
258
         return 0;
241
262
      grub_uint32_t value;
242
263
      grub_uint8_t alpha = 255; /* Opaque color.  */
243
264
 
244
 
      red >>= 8 - render_target->mode_info.red_mask_size;
245
 
      green >>= 8 - render_target->mode_info.green_mask_size;
246
 
      blue >>= 8 - render_target->mode_info.blue_mask_size;
247
 
      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
 
265
      red >>= 8 - framebuffer.render_target->mode_info.red_mask_size;
 
266
      green >>= 8 - framebuffer.render_target->mode_info.green_mask_size;
 
267
      blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size;
 
268
      alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size;
248
269
 
249
 
      value = red << render_target->mode_info.red_field_pos;
250
 
      value |= green << render_target->mode_info.green_field_pos;
251
 
      value |= blue << render_target->mode_info.blue_field_pos;
252
 
      value |= alpha << render_target->mode_info.reserved_field_pos;
 
270
      value = red << framebuffer.render_target->mode_info.red_field_pos;
 
271
      value |= green << framebuffer.render_target->mode_info.green_field_pos;
 
272
      value |= blue << framebuffer.render_target->mode_info.blue_field_pos;
 
273
      value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos;
253
274
 
254
275
      return value;
255
276
    }
261
282
grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green,
262
283
                        grub_uint8_t blue, grub_uint8_t alpha)
263
284
{
264
 
  if ((render_target->mode_info.mode_type
 
285
  if ((framebuffer.render_target->mode_info.mode_type
265
286
       & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
266
287
    /* No alpha available in index color modes, just use
267
288
       same value as in only RGB modes.  */
268
289
    return grub_video_fb_map_rgb (red, green, blue);
269
 
  else if ((render_target->mode_info.mode_type
 
290
  else if ((framebuffer.render_target->mode_info.mode_type
270
291
            & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
271
292
    {
272
 
      if (red == render_target->mode_info.fg_red
273
 
          && green == render_target->mode_info.fg_green
274
 
          && blue == render_target->mode_info.fg_blue
275
 
          && alpha == render_target->mode_info.fg_alpha)
 
293
      if (red == framebuffer.render_target->mode_info.fg_red
 
294
          && green == framebuffer.render_target->mode_info.fg_green
 
295
          && blue == framebuffer.render_target->mode_info.fg_blue
 
296
          && alpha == framebuffer.render_target->mode_info.fg_alpha)
276
297
        return 1;
277
298
      else
278
299
        return 0;
281
302
    {
282
303
      grub_uint32_t value;
283
304
 
284
 
      red >>= 8 - render_target->mode_info.red_mask_size;
285
 
      green >>= 8 - render_target->mode_info.green_mask_size;
286
 
      blue >>= 8 - render_target->mode_info.blue_mask_size;
287
 
      alpha >>= 8 - render_target->mode_info.reserved_mask_size;
 
305
      red >>= 8 - framebuffer.render_target->mode_info.red_mask_size;
 
306
      green >>= 8 - framebuffer.render_target->mode_info.green_mask_size;
 
307
      blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size;
 
308
      alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size;
288
309
 
289
 
      value = red << render_target->mode_info.red_field_pos;
290
 
      value |= green << render_target->mode_info.green_field_pos;
291
 
      value |= blue << render_target->mode_info.blue_field_pos;
292
 
      value |= alpha << render_target->mode_info.reserved_field_pos;
 
310
      value = red << framebuffer.render_target->mode_info.red_field_pos;
 
311
      value |= green << framebuffer.render_target->mode_info.green_field_pos;
 
312
      value |= blue << framebuffer.render_target->mode_info.blue_field_pos;
 
313
      value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos;
293
314
 
294
315
      return value;
295
316
    }
303
324
{
304
325
  struct grub_video_fbblit_info target_info;
305
326
 
306
 
  target_info.mode_info = &render_target->mode_info;
307
 
  target_info.data = render_target->data;
 
327
  target_info.mode_info = &framebuffer.render_target->mode_info;
 
328
  target_info.data = framebuffer.render_target->data;
308
329
 
309
330
  grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha);
310
331
 
334
355
          return;
335
356
        }
336
357
 
337
 
      *red = palette[color].r;
338
 
      *green = palette[color].g;
339
 
      *blue = palette[color].b;
340
 
      *alpha = palette[color].a;
 
358
      *red = framebuffer.palette[color].r;
 
359
      *green = framebuffer.palette[color].g;
 
360
      *blue = framebuffer.palette[color].b;
 
361
      *alpha = framebuffer.palette[color].a;
341
362
      return;
342
363
    }
343
364
  else if ((mode_info->mode_type
406
427
  struct grub_video_fbblit_info target;
407
428
 
408
429
  /* Make sure there is something to do.  */
409
 
  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
 
430
  if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
410
431
    return GRUB_ERR_NONE;
411
 
  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
 
432
  if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
412
433
    return GRUB_ERR_NONE;
413
434
 
414
435
  /* Do not allow drawing out of viewport.  */
423
444
      y = 0;
424
445
    }
425
446
 
426
 
  if ((x + width) > render_target->viewport.width)
427
 
    width = render_target->viewport.width - x;
428
 
  if ((y + height) > render_target->viewport.height)
429
 
    height = render_target->viewport.height - y;
 
447
  if ((x + width) > framebuffer.render_target->viewport.width)
 
448
    width = framebuffer.render_target->viewport.width - x;
 
449
  if ((y + height) > framebuffer.render_target->viewport.height)
 
450
    height = framebuffer.render_target->viewport.height - y;
430
451
 
431
452
  /* Add viewport offset.  */
432
 
  x += render_target->viewport.x;
433
 
  y += render_target->viewport.y;
 
453
  x += framebuffer.render_target->viewport.x;
 
454
  y += framebuffer.render_target->viewport.y;
434
455
 
435
456
  /* Use fbblit_info to encapsulate rendering.  */
436
 
  target.mode_info = &render_target->mode_info;
437
 
  target.data = render_target->data;
 
457
  target.mode_info = &framebuffer.render_target->mode_info;
 
458
  target.data = framebuffer.render_target->data;
438
459
 
439
460
  /* Try to figure out more optimized version.  Note that color is already
440
461
     mapped to target format so we can make assumptions based on that.  */
761
782
  /* Make sure there is something to do.  */
762
783
  if ((width == 0) || (height == 0))
763
784
    return GRUB_ERR_NONE;
764
 
  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
 
785
  if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
765
786
    return GRUB_ERR_NONE;
766
 
  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
 
787
  if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
767
788
    return GRUB_ERR_NONE;
768
789
  if ((x + (int)bitmap->mode_info.width) < 0)
769
790
    return GRUB_ERR_NONE;
806
827
    }
807
828
 
808
829
  /* Do not allow drawing out of viewport.  */
809
 
  if ((x + width) > render_target->viewport.width)
810
 
    width = render_target->viewport.width - x;
811
 
  if ((y + height) > render_target->viewport.height)
812
 
    height = render_target->viewport.height - y;
 
830
  if ((x + width) > framebuffer.render_target->viewport.width)
 
831
    width = framebuffer.render_target->viewport.width - x;
 
832
  if ((y + height) > framebuffer.render_target->viewport.height)
 
833
    height = framebuffer.render_target->viewport.height - y;
813
834
 
814
835
  if ((offset_x + width) > bitmap->mode_info.width)
815
836
    width = bitmap->mode_info.width - offset_x;
824
845
    height = bitmap->mode_info.height;
825
846
 
826
847
  /* Add viewport offset.  */
827
 
  x += render_target->viewport.x;
828
 
  y += render_target->viewport.y;
 
848
  x += framebuffer.render_target->viewport.x;
 
849
  y += framebuffer.render_target->viewport.y;
829
850
 
830
851
  /* Use fbblit_info to encapsulate rendering.  */
831
852
  source.mode_info = &bitmap->mode_info;
832
853
  source.data = bitmap->data;
833
 
  target.mode_info = &render_target->mode_info;
834
 
  target.data = render_target->data;
 
854
  target.mode_info = &framebuffer.render_target->mode_info;
 
855
  target.data = framebuffer.render_target->data;
835
856
 
836
857
  /* Do actual blitting.  */
837
858
  common_blitter (&target, &source, oper, x, y, width, height,
852
873
  /* Make sure there is something to do.  */
853
874
  if ((width == 0) || (height == 0))
854
875
    return GRUB_ERR_NONE;
855
 
  if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
 
876
  if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
856
877
    return GRUB_ERR_NONE;
857
 
  if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
 
878
  if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
858
879
    return GRUB_ERR_NONE;
859
880
  if ((x + (int)source->mode_info.width) < 0)
860
881
    return GRUB_ERR_NONE;
897
918
    }
898
919
 
899
920
  /* Do not allow drawing out of viewport.  */
900
 
  if ((x + width) > render_target->viewport.width)
901
 
    width = render_target->viewport.width - x;
902
 
  if ((y + height) > render_target->viewport.height)
903
 
    height = render_target->viewport.height - y;
 
921
  if ((x + width) > framebuffer.render_target->viewport.width)
 
922
    width = framebuffer.render_target->viewport.width - x;
 
923
  if ((y + height) > framebuffer.render_target->viewport.height)
 
924
    height = framebuffer.render_target->viewport.height - y;
904
925
 
905
926
  if ((offset_x + width) > source->mode_info.width)
906
927
    width = source->mode_info.width - offset_x;
915
936
    height = source->mode_info.height;
916
937
 
917
938
  /* Add viewport offset.  */
918
 
  x += render_target->viewport.x;
919
 
  y += render_target->viewport.y;
 
939
  x += framebuffer.render_target->viewport.x;
 
940
  y += framebuffer.render_target->viewport.y;
920
941
 
921
942
  /* Use fbblit_info to encapsulate rendering.  */
922
943
  source_info.mode_info = &source->mode_info;
923
944
  source_info.data = source->data;
924
 
  target_info.mode_info = &render_target->mode_info;
925
 
  target_info.data = render_target->data;
 
945
  target_info.mode_info = &framebuffer.render_target->mode_info;
 
946
  target_info.data = framebuffer.render_target->data;
926
947
 
927
948
  /* Do actual blitting.  */
928
949
  common_blitter (&target_info, &source_info, oper, x, y, width, height,
945
966
  if ((dx == 0) && (dy == 0))
946
967
    return GRUB_ERR_NONE;
947
968
 
948
 
  width = render_target->viewport.width - grub_abs (dx);
949
 
  height = render_target->viewport.height - grub_abs (dy);
 
969
  width = framebuffer.render_target->viewport.width - grub_abs (dx);
 
970
  height = framebuffer.render_target->viewport.height - grub_abs (dy);
950
971
 
951
972
  if (dx < 0)
952
973
    {
953
 
      src_x = render_target->viewport.x - dx;
954
 
      dst_x = render_target->viewport.x;
 
974
      src_x = framebuffer.render_target->viewport.x - dx;
 
975
      dst_x = framebuffer.render_target->viewport.x;
955
976
    }
956
977
  else
957
978
    {
958
 
      src_x = render_target->viewport.x;
959
 
      dst_x = render_target->viewport.x + dx;
 
979
      src_x = framebuffer.render_target->viewport.x;
 
980
      dst_x = framebuffer.render_target->viewport.x + dx;
960
981
    }
961
982
 
962
983
  if (dy < 0)
963
984
    {
964
 
      src_y = render_target->viewport.y - dy;
965
 
      dst_y = render_target->viewport.y;
 
985
      src_y = framebuffer.render_target->viewport.y - dy;
 
986
      dst_y = framebuffer.render_target->viewport.y;
966
987
    }
967
988
  else
968
989
    {
969
 
      src_y = render_target->viewport.y;
970
 
      dst_y = render_target->viewport.y + dy;
 
990
      src_y = framebuffer.render_target->viewport.y;
 
991
      dst_y = framebuffer.render_target->viewport.y + dy;
971
992
    }
972
993
 
973
994
  /* 2. Check if there is need to copy data.  */
974
 
  if ((grub_abs (dx) < render_target->viewport.width)
975
 
       && (grub_abs (dy) < render_target->viewport.height))
 
995
  if ((grub_abs (dx) < framebuffer.render_target->viewport.width)
 
996
       && (grub_abs (dy) < framebuffer.render_target->viewport.height))
976
997
    {
977
998
      /* 3. Move data in render target.  */
978
999
      struct grub_video_fbblit_info target;
979
1000
      int i, j;
980
1001
      int linedelta, linelen;
981
1002
 
982
 
      target.mode_info = &render_target->mode_info;
983
 
      target.data = render_target->data;
 
1003
      target.mode_info = &framebuffer.render_target->mode_info;
 
1004
      target.data = framebuffer.render_target->data;
984
1005
 
985
1006
      linedelta = target.mode_info->pitch
986
1007
        - width * target.mode_info->bytes_per_pixel;
1063
1084
 
1064
1085
  /* 4a. Fill top & bottom parts.  */
1065
1086
  if (dy > 0)
1066
 
    grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy);
 
1087
    grub_video_fb_fill_rect (color, 0, 0, framebuffer.render_target->viewport.width, dy);
1067
1088
  else if (dy < 0)
1068
1089
    {
1069
 
      if (render_target->viewport.height < grub_abs (dy))
1070
 
        dy = -render_target->viewport.height;
 
1090
      if (framebuffer.render_target->viewport.height < grub_abs (dy))
 
1091
        dy = -framebuffer.render_target->viewport.height;
1071
1092
 
1072
 
      grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy,
1073
 
                                render_target->viewport.width, -dy);
 
1093
      grub_video_fb_fill_rect (color, 0, framebuffer.render_target->viewport.height + dy,
 
1094
                                framebuffer.render_target->viewport.width, -dy);
1074
1095
    }
1075
1096
 
1076
1097
  /* 4b. Fill left & right parts.  */
1077
1098
  if (dx > 0)
1078
1099
    grub_video_fb_fill_rect (color, 0, 0,
1079
 
                              dx, render_target->viewport.height);
 
1100
                              dx, framebuffer.render_target->viewport.height);
1080
1101
  else if (dx < 0)
1081
1102
    {
1082
 
      if (render_target->viewport.width < grub_abs (dx))
1083
 
        dx = -render_target->viewport.width;
 
1103
      if (framebuffer.render_target->viewport.width < grub_abs (dx))
 
1104
        dx = -framebuffer.render_target->viewport.width;
1084
1105
 
1085
 
      grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0,
1086
 
                                -dx, render_target->viewport.height);
 
1106
      grub_video_fb_fill_rect (color, framebuffer.render_target->viewport.width + dx, 0,
 
1107
                                -dx, framebuffer.render_target->viewport.height);
1087
1108
    }
1088
1109
 
1089
1110
  return GRUB_ERR_NONE;
1130
1151
  target->mode_info.bpp = 32;
1131
1152
  target->mode_info.bytes_per_pixel = 4;
1132
1153
  target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
1133
 
  target->mode_info.number_of_colors = palette_size; /* Emulated palette.  */
 
1154
  target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette.  */
1134
1155
  target->mode_info.red_mask_size = 8;
1135
1156
  target->mode_info.red_field_pos = 0;
1136
1157
  target->mode_info.green_mask_size = 8;
1221
1242
grub_err_t
1222
1243
grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target)
1223
1244
{
 
1245
  if (target == (struct grub_video_fbrender_target *)
 
1246
      GRUB_VIDEO_RENDER_TARGET_DISPLAY)
 
1247
    target = framebuffer.back_target;
 
1248
 
1224
1249
  if (! target->data)
1225
1250
    return grub_error (GRUB_ERR_BAD_ARGUMENT,
1226
1251
                       "invalid render target given");
1227
1252
 
1228
 
  render_target = target;
 
1253
  framebuffer.render_target = target;
1229
1254
 
1230
1255
  return GRUB_ERR_NONE;
1231
1256
}
1233
1258
grub_err_t
1234
1259
grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target)
1235
1260
{
1236
 
  *target = render_target;
 
1261
  *target = framebuffer.render_target;
 
1262
 
 
1263
  if (*target == framebuffer.back_target)
 
1264
    *target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY;
1237
1265
 
1238
1266
  return GRUB_ERR_NONE;
1239
1267
}
1247
1275
  return GRUB_ERR_NONE;
1248
1276
}
1249
1277
 
1250
 
grub_err_t
 
1278
static grub_err_t
1251
1279
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
1252
1280
                                   struct grub_video_fbrender_target **back,
1253
 
                                   grub_video_fb_doublebuf_update_screen_t *update_screen,
1254
1281
                                   struct grub_video_mode_info mode_info,
1255
1282
                                   void *framebuf)
1256
1283
{
1257
1284
  grub_err_t err;
1258
1285
  int page_size = mode_info.pitch * mode_info.height;
1259
 
  void *offscreen_buffer;
1260
1286
 
1261
1287
  err = grub_video_fb_create_render_target_from_pointer (front, &mode_info,
1262
1288
                                                         framebuf);
1263
1289
  if (err)
1264
1290
    return err;
1265
1291
 
1266
 
  offscreen_buffer = grub_malloc (page_size);
1267
 
  if (! offscreen_buffer)
 
1292
  framebuffer.offscreen_buffer = grub_malloc (page_size);
 
1293
  if (! framebuffer.offscreen_buffer)
1268
1294
    {
1269
1295
      grub_video_fb_delete_render_target (*front);
1270
1296
      *front = 0;
1272
1298
    }
1273
1299
 
1274
1300
  err = grub_video_fb_create_render_target_from_pointer (back, &mode_info,
1275
 
                                                         offscreen_buffer);
 
1301
                                                         framebuffer.offscreen_buffer);
1276
1302
 
1277
1303
  if (err)
1278
1304
    {
1279
1305
      grub_video_fb_delete_render_target (*front);
1280
 
      grub_free (offscreen_buffer);
 
1306
      grub_free (framebuffer.offscreen_buffer);
 
1307
      framebuffer.offscreen_buffer = 0;
1281
1308
      *front = 0;
1282
1309
      return grub_errno;
1283
1310
    }
1284
1311
  (*back)->is_allocated = 1;
1285
1312
 
1286
 
  *update_screen = doublebuf_blit_update_screen;
 
1313
  framebuffer.update_screen = doublebuf_blit_update_screen;
 
1314
 
 
1315
  return GRUB_ERR_NONE;
 
1316
}
 
1317
 
 
1318
static grub_err_t
 
1319
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
 
1320
                                      __attribute__ ((unused)),
 
1321
                                      struct grub_video_fbrender_target *back
 
1322
                                      __attribute__ ((unused)))
 
1323
{
 
1324
  int new_displayed_page;
 
1325
  struct grub_video_fbrender_target *target;
 
1326
  grub_err_t err;
 
1327
 
 
1328
  /* Swap the page numbers in the framebuffer struct.  */
 
1329
  new_displayed_page = framebuffer.render_page;
 
1330
  framebuffer.render_page = framebuffer.displayed_page;
 
1331
  framebuffer.displayed_page = new_displayed_page;
 
1332
 
 
1333
  err = framebuffer.set_page (framebuffer.displayed_page);
 
1334
  if (err)
 
1335
    {
 
1336
      /* Restore previous state.  */
 
1337
      framebuffer.render_page = framebuffer.displayed_page;
 
1338
      framebuffer.displayed_page = new_displayed_page;
 
1339
      return err;
 
1340
    }
 
1341
 
 
1342
  target = framebuffer.back_target;
 
1343
  framebuffer.back_target = framebuffer.front_target;
 
1344
  framebuffer.front_target = target;
 
1345
 
 
1346
  if (framebuffer.front_target->mode_info.mode_type
 
1347
      & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
 
1348
    grub_memcpy (framebuffer.back_target->data, framebuffer.front_target->data,
 
1349
                 framebuffer.back_target->mode_info.pitch
 
1350
                 * framebuffer.back_target->mode_info.height);
 
1351
 
 
1352
  err = grub_video_fb_get_active_render_target (&target);
 
1353
  if (err)
 
1354
    return err;
 
1355
 
 
1356
  if (framebuffer.render_target == framebuffer.back_target)
 
1357
    framebuffer.render_target = framebuffer.front_target;
 
1358
  else if (framebuffer.render_target == framebuffer.front_target)
 
1359
    framebuffer.render_target = framebuffer.back_target;
 
1360
 
 
1361
  return err;
 
1362
}
 
1363
 
 
1364
static grub_err_t
 
1365
doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info,
 
1366
                             volatile void *page0_ptr,
 
1367
                             grub_video_fb_set_page_t set_page_in,
 
1368
                             volatile void *page1_ptr)
 
1369
{
 
1370
  grub_err_t err;
 
1371
 
 
1372
  framebuffer.displayed_page = 0;
 
1373
  framebuffer.render_page = 1;
 
1374
 
 
1375
  framebuffer.update_screen = doublebuf_pageflipping_update_screen;
 
1376
 
 
1377
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target,
 
1378
                                                         mode_info,
 
1379
                                                         (void *) page0_ptr);
 
1380
  if (err)
 
1381
    return err;
 
1382
 
 
1383
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target,
 
1384
                                                         mode_info,
 
1385
                                                         (void *) page1_ptr);
 
1386
  if (err)
 
1387
    {
 
1388
      grub_video_fb_delete_render_target (framebuffer.front_target);
 
1389
      return err;
 
1390
    }
 
1391
 
 
1392
  /* Set the framebuffer memory data pointer and display the right page.  */
 
1393
  err = set_page_in (framebuffer.displayed_page);
 
1394
  if (err)
 
1395
    {
 
1396
      grub_video_fb_delete_render_target (framebuffer.front_target);
 
1397
      grub_video_fb_delete_render_target (framebuffer.back_target);
 
1398
      return err;
 
1399
    }
 
1400
  framebuffer.set_page = set_page_in;
 
1401
 
 
1402
  return GRUB_ERR_NONE;
 
1403
}
 
1404
 
 
1405
/* Select the best double buffering mode available.  */
 
1406
grub_err_t
 
1407
grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
 
1408
                     struct grub_video_mode_info *mode_info,
 
1409
                     volatile void *page0_ptr,
 
1410
                     grub_video_fb_set_page_t set_page_in,
 
1411
                     volatile void *page1_ptr)
 
1412
{
 
1413
  grub_err_t err;
 
1414
  int updating_swap_needed;
 
1415
 
 
1416
  updating_swap_needed
 
1417
    = grub_video_check_mode_flag (mode_type, mode_mask,
 
1418
                                  GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
 
1419
 
 
1420
  /* Do double buffering only if it's either requested or efficient.  */
 
1421
  if (set_page_in && grub_video_check_mode_flag (mode_type, mode_mask,
 
1422
                                                 GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
 
1423
                                                 !updating_swap_needed))
 
1424
    {
 
1425
      mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
 
1426
      if (updating_swap_needed)
 
1427
        mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
 
1428
 
 
1429
      err = doublebuf_pageflipping_init (mode_info, page0_ptr,
 
1430
                                         set_page_in,
 
1431
                                         page1_ptr);
 
1432
      if (!err)
 
1433
        {
 
1434
          framebuffer.render_target = framebuffer.back_target;
 
1435
          return GRUB_ERR_NONE;
 
1436
        }
 
1437
      
 
1438
      mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
 
1439
                                | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
 
1440
 
 
1441
      grub_errno = GRUB_ERR_NONE;
 
1442
    }
 
1443
 
 
1444
  if (grub_video_check_mode_flag (mode_type, mode_mask,
 
1445
                                  GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
 
1446
                                  0))
 
1447
    {
 
1448
      mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
 
1449
                               | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
 
1450
 
 
1451
      err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target,
 
1452
                                               &framebuffer.back_target,
 
1453
                                               *mode_info,
 
1454
                                               (void *) page0_ptr);
 
1455
 
 
1456
      if (!err)
 
1457
        {
 
1458
          framebuffer.render_target = framebuffer.back_target;
 
1459
          return GRUB_ERR_NONE;
 
1460
        }
 
1461
 
 
1462
      mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
 
1463
                                | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
 
1464
 
 
1465
      grub_errno = GRUB_ERR_NONE;
 
1466
    }
 
1467
 
 
1468
  /* Fall back to no double buffering.  */
 
1469
  err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target,
 
1470
                                                         mode_info,
 
1471
                                                         (void *) page0_ptr);
 
1472
 
 
1473
  if (err)
 
1474
    return err;
 
1475
 
 
1476
  framebuffer.back_target = framebuffer.front_target;
 
1477
  framebuffer.update_screen = 0;
 
1478
 
 
1479
  mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
 
1480
 
 
1481
  framebuffer.render_target = framebuffer.back_target;
 
1482
 
 
1483
  return GRUB_ERR_NONE;
 
1484
}
 
1485
 
 
1486
 
 
1487
grub_err_t
 
1488
grub_video_fb_swap_buffers (void)
 
1489
{
 
1490
  grub_err_t err;
 
1491
  if (!framebuffer.update_screen)
 
1492
    return GRUB_ERR_NONE;
 
1493
 
 
1494
  err = framebuffer.update_screen (framebuffer.front_target,
 
1495
                                   framebuffer.back_target);
 
1496
  if (err)
 
1497
    return err;
 
1498
 
 
1499
  return GRUB_ERR_NONE;
 
1500
}
 
1501
 
 
1502
grub_err_t
 
1503
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
 
1504
                                 void **framebuf)
 
1505
{
 
1506
  grub_memcpy (mode_info, &(framebuffer.front_target->mode_info),
 
1507
               sizeof (*mode_info));
 
1508
  *framebuf = framebuffer.front_target->data;
 
1509
 
 
1510
  grub_video_fb_fini ();
1287
1511
 
1288
1512
  return GRUB_ERR_NONE;
1289
1513
}