1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2007 The Android Open Source Project
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun * You may obtain a copy of the License at
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun * limitations under the License.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <stdbool.h>
18*4882a593Smuzhiyun #include <stdlib.h>
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun #include <unistd.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <fcntl.h>
23*4882a593Smuzhiyun #include <stdio.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <sys/ioctl.h>
26*4882a593Smuzhiyun #include <sys/mman.h>
27*4882a593Smuzhiyun #include <sys/types.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include <linux/fb.h>
30*4882a593Smuzhiyun #include <linux/kd.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <time.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include "font_10x18.h"
35*4882a593Smuzhiyun #include "minui.h"
36*4882a593Smuzhiyun #include "graphics.h"
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun typedef struct {
39*4882a593Smuzhiyun GRSurface* texture;
40*4882a593Smuzhiyun int cwidth;
41*4882a593Smuzhiyun int cheight;
42*4882a593Smuzhiyun } GRFont;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun static GRFont* gr_font = NULL;
45*4882a593Smuzhiyun static minui_backend* gr_backend = NULL;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static int overscan_percent = 0;
48*4882a593Smuzhiyun static int overscan_offset_x = 0;
49*4882a593Smuzhiyun static int overscan_offset_y = 0;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun static int gr_vt_fd = -1;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static unsigned char gr_current_r = 255;
54*4882a593Smuzhiyun static unsigned char gr_current_g = 255;
55*4882a593Smuzhiyun static unsigned char gr_current_b = 255;
56*4882a593Smuzhiyun static unsigned char gr_current_a = 255;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun static GRSurface* gr_draw = NULL;
59*4882a593Smuzhiyun
outside(int x,int y)60*4882a593Smuzhiyun static bool outside(int x, int y)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
gr_measure(const char * s)65*4882a593Smuzhiyun int gr_measure(const char *s)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun return gr_font->cwidth * strlen(s);
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
gr_font_size(int * x,int * y)70*4882a593Smuzhiyun void gr_font_size(int *x, int *y)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun *x = gr_font->cwidth;
73*4882a593Smuzhiyun *y = gr_font->cheight;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
text_blend(unsigned char * src_p,int src_row_bytes,unsigned char * dst_p,int dst_row_bytes,int width,int height)76*4882a593Smuzhiyun static void text_blend(unsigned char* src_p, int src_row_bytes,
77*4882a593Smuzhiyun unsigned char* dst_p, int dst_row_bytes,
78*4882a593Smuzhiyun int width, int height)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun int i, j;
81*4882a593Smuzhiyun for (j = 0; j < height; ++j) {
82*4882a593Smuzhiyun unsigned char* sx = src_p;
83*4882a593Smuzhiyun unsigned char* px = dst_p;
84*4882a593Smuzhiyun for (i = 0; i < width; ++i) {
85*4882a593Smuzhiyun unsigned char a = *sx++;
86*4882a593Smuzhiyun if (gr_current_a < 255) a = ((int)a * gr_current_a) / 255;
87*4882a593Smuzhiyun if (a == 255) {
88*4882a593Smuzhiyun *px++ = gr_current_r;
89*4882a593Smuzhiyun *px++ = gr_current_g;
90*4882a593Smuzhiyun *px++ = gr_current_b;
91*4882a593Smuzhiyun px++;
92*4882a593Smuzhiyun } else if (a > 0) {
93*4882a593Smuzhiyun *px = (*px * (255-a) + gr_current_r * a) / 255;
94*4882a593Smuzhiyun ++px;
95*4882a593Smuzhiyun *px = (*px * (255-a) + gr_current_g * a) / 255;
96*4882a593Smuzhiyun ++px;
97*4882a593Smuzhiyun *px = (*px * (255-a) + gr_current_b * a) / 255;
98*4882a593Smuzhiyun ++px;
99*4882a593Smuzhiyun ++px;
100*4882a593Smuzhiyun } else {
101*4882a593Smuzhiyun px += 4;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun src_p += src_row_bytes;
105*4882a593Smuzhiyun dst_p += dst_row_bytes;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
gr_text(int x,int y,const char * s,int bold)109*4882a593Smuzhiyun void gr_text(int x, int y, const char *s, int bold)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun GRFont *font = gr_font;
112*4882a593Smuzhiyun unsigned off;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (!font->texture) return;
115*4882a593Smuzhiyun if (gr_current_a == 0) return;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun bold = bold && (font->texture->height != font->cheight);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun x += overscan_offset_x;
120*4882a593Smuzhiyun y += overscan_offset_y;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun while((off = *s++)) {
123*4882a593Smuzhiyun off -= 32;
124*4882a593Smuzhiyun if (outside(x, y) || outside(x+font->cwidth-1, y+font->cheight-1)) break;
125*4882a593Smuzhiyun if (off < 96) {
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun unsigned char* src_p = font->texture->data + (off * font->cwidth) +
128*4882a593Smuzhiyun (bold ? font->cheight * font->texture->row_bytes : 0);
129*4882a593Smuzhiyun unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun text_blend(src_p, font->texture->row_bytes,
132*4882a593Smuzhiyun dst_p, gr_draw->row_bytes,
133*4882a593Smuzhiyun font->cwidth, font->cheight);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun x += font->cwidth;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
gr_texticon(int x,int y,GRSurface * icon)140*4882a593Smuzhiyun void gr_texticon(int x, int y, GRSurface* icon) {
141*4882a593Smuzhiyun if (icon == NULL) return;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (icon->pixel_bytes != 1) {
144*4882a593Smuzhiyun printf("gr_texticon: source has wrong format\n");
145*4882a593Smuzhiyun return;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun x += overscan_offset_x;
149*4882a593Smuzhiyun y += overscan_offset_y;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (outside(x, y) || outside(x+icon->width-1, y+icon->height-1)) return;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun unsigned char* src_p = icon->data;
154*4882a593Smuzhiyun unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun text_blend(src_p, icon->row_bytes,
157*4882a593Smuzhiyun dst_p, gr_draw->row_bytes,
158*4882a593Smuzhiyun icon->width, icon->height);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
gr_color(unsigned char r,unsigned char g,unsigned char b,unsigned char a)161*4882a593Smuzhiyun void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun gr_current_r = r;
164*4882a593Smuzhiyun gr_current_g = g;
165*4882a593Smuzhiyun gr_current_b = b;
166*4882a593Smuzhiyun gr_current_a = a;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
gr_clear()169*4882a593Smuzhiyun void gr_clear()
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun if (gr_current_r == gr_current_g &&
172*4882a593Smuzhiyun gr_current_r == gr_current_b) {
173*4882a593Smuzhiyun memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes);
174*4882a593Smuzhiyun } else {
175*4882a593Smuzhiyun int x, y;
176*4882a593Smuzhiyun unsigned char* px = gr_draw->data;
177*4882a593Smuzhiyun for (y = 0; y < gr_draw->height; ++y) {
178*4882a593Smuzhiyun for (x = 0; x < gr_draw->width; ++x) {
179*4882a593Smuzhiyun *px++ = gr_current_r;
180*4882a593Smuzhiyun *px++ = gr_current_g;
181*4882a593Smuzhiyun *px++ = gr_current_b;
182*4882a593Smuzhiyun px++;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun px += gr_draw->row_bytes - (gr_draw->width * gr_draw->pixel_bytes);
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
gr_fill(int x1,int y1,int x2,int y2)189*4882a593Smuzhiyun void gr_fill(int x1, int y1, int x2, int y2)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun x1 += overscan_offset_x;
192*4882a593Smuzhiyun y1 += overscan_offset_y;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun x2 += overscan_offset_x;
195*4882a593Smuzhiyun y2 += overscan_offset_y;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (outside(x1, y1) || outside(x2-1, y2-1)) return;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun unsigned char* p = gr_draw->data + y1 * gr_draw->row_bytes + x1 * gr_draw->pixel_bytes;
200*4882a593Smuzhiyun if (gr_current_a == 255) {
201*4882a593Smuzhiyun int x, y;
202*4882a593Smuzhiyun for (y = y1; y < y2; ++y) {
203*4882a593Smuzhiyun unsigned char* px = p;
204*4882a593Smuzhiyun for (x = x1; x < x2; ++x) {
205*4882a593Smuzhiyun *px++ = gr_current_r;
206*4882a593Smuzhiyun *px++ = gr_current_g;
207*4882a593Smuzhiyun *px++ = gr_current_b;
208*4882a593Smuzhiyun px++;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun p += gr_draw->row_bytes;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun } else if (gr_current_a > 0) {
213*4882a593Smuzhiyun int x, y;
214*4882a593Smuzhiyun for (y = y1; y < y2; ++y) {
215*4882a593Smuzhiyun unsigned char* px = p;
216*4882a593Smuzhiyun for (x = x1; x < x2; ++x) {
217*4882a593Smuzhiyun *px = (*px * (255-gr_current_a) + gr_current_r * gr_current_a) / 255;
218*4882a593Smuzhiyun ++px;
219*4882a593Smuzhiyun *px = (*px * (255-gr_current_a) + gr_current_g * gr_current_a) / 255;
220*4882a593Smuzhiyun ++px;
221*4882a593Smuzhiyun *px = (*px * (255-gr_current_a) + gr_current_b * gr_current_a) / 255;
222*4882a593Smuzhiyun ++px;
223*4882a593Smuzhiyun ++px;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun p += gr_draw->row_bytes;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
gr_blit(GRSurface * source,int sx,int sy,int w,int h,int dx,int dy)230*4882a593Smuzhiyun void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
231*4882a593Smuzhiyun if (source == NULL) return;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun if (gr_draw->pixel_bytes != source->pixel_bytes) {
234*4882a593Smuzhiyun printf("gr_blit: source has wrong format\n");
235*4882a593Smuzhiyun return;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun dx += overscan_offset_x;
239*4882a593Smuzhiyun dy += overscan_offset_y;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes;
244*4882a593Smuzhiyun unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun int i;
247*4882a593Smuzhiyun for (i = 0; i < h; ++i) {
248*4882a593Smuzhiyun memcpy(dst_p, src_p, w * source->pixel_bytes);
249*4882a593Smuzhiyun src_p += source->row_bytes;
250*4882a593Smuzhiyun dst_p += gr_draw->row_bytes;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
gr_get_width(GRSurface * surface)254*4882a593Smuzhiyun unsigned int gr_get_width(GRSurface* surface) {
255*4882a593Smuzhiyun if (surface == NULL) {
256*4882a593Smuzhiyun return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun return surface->width;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
gr_get_height(GRSurface * surface)261*4882a593Smuzhiyun unsigned int gr_get_height(GRSurface* surface) {
262*4882a593Smuzhiyun if (surface == NULL) {
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun return surface->height;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
gr_init_font(void)268*4882a593Smuzhiyun static void gr_init_font(void)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun gr_font = calloc(sizeof(*gr_font), 1);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun int res = res_create_alpha_surface("font", &(gr_font->texture));
273*4882a593Smuzhiyun if (res == 0) {
274*4882a593Smuzhiyun // The font image should be a 96x2 array of character images. The
275*4882a593Smuzhiyun // columns are the printable ASCII characters 0x20 - 0x7f. The
276*4882a593Smuzhiyun // top row is regular text; the bottom row is bold.
277*4882a593Smuzhiyun gr_font->cwidth = gr_font->texture->width / 96;
278*4882a593Smuzhiyun gr_font->cheight = gr_font->texture->height / 2;
279*4882a593Smuzhiyun } else {
280*4882a593Smuzhiyun printf("failed to read font: res=%d\n", res);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun // fall back to the compiled-in font.
283*4882a593Smuzhiyun gr_font->texture = malloc(sizeof(*gr_font->texture));
284*4882a593Smuzhiyun gr_font->texture->width = font.width;
285*4882a593Smuzhiyun gr_font->texture->height = font.height;
286*4882a593Smuzhiyun gr_font->texture->row_bytes = font.width;
287*4882a593Smuzhiyun gr_font->texture->pixel_bytes = 1;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun unsigned char* bits = malloc(font.width * font.height);
290*4882a593Smuzhiyun gr_font->texture->data = (void*) bits;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun unsigned char data;
293*4882a593Smuzhiyun unsigned char* in = font.rundata;
294*4882a593Smuzhiyun while((data = *in++)) {
295*4882a593Smuzhiyun memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
296*4882a593Smuzhiyun bits += (data & 0x7f);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun gr_font->cwidth = font.cwidth;
300*4882a593Smuzhiyun gr_font->cheight = font.cheight;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun #if 0
305*4882a593Smuzhiyun // Exercises many of the gr_*() functions; useful for testing.
306*4882a593Smuzhiyun static void gr_test() {
307*4882a593Smuzhiyun GRSurface** images;
308*4882a593Smuzhiyun int frames;
309*4882a593Smuzhiyun int result = res_create_multi_surface("icon_installing", &frames, &images);
310*4882a593Smuzhiyun if (result < 0) {
311*4882a593Smuzhiyun printf("create surface %d\n", result);
312*4882a593Smuzhiyun gr_exit();
313*4882a593Smuzhiyun return;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun time_t start = time(NULL);
317*4882a593Smuzhiyun int x;
318*4882a593Smuzhiyun for (x = 0; x <= 1200; ++x) {
319*4882a593Smuzhiyun if (x < 400) {
320*4882a593Smuzhiyun gr_color(0, 0, 0, 255);
321*4882a593Smuzhiyun } else {
322*4882a593Smuzhiyun gr_color(0, (x-400)%128, 0, 255);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun gr_clear();
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun gr_color(255, 0, 0, 255);
327*4882a593Smuzhiyun gr_surface frame = images[x%frames];
328*4882a593Smuzhiyun gr_blit(frame, 0, 0, frame->width, frame->height, x, 0);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun gr_color(255, 0, 0, 128);
331*4882a593Smuzhiyun gr_fill(400, 150, 600, 350);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun gr_color(255, 255, 255, 255);
334*4882a593Smuzhiyun gr_text(500, 225, "hello, world!", 0);
335*4882a593Smuzhiyun gr_color(255, 255, 0, 128);
336*4882a593Smuzhiyun gr_text(300+x, 275, "pack my box with five dozen liquor jugs", 1);
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun gr_color(0, 0, 255, 128);
339*4882a593Smuzhiyun gr_fill(gr_draw->width - 200 - x, 300, gr_draw->width - x, 500);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun gr_draw = gr_backend->flip(gr_backend);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun printf("getting end time\n");
344*4882a593Smuzhiyun time_t end = time(NULL);
345*4882a593Smuzhiyun printf("got end time\n");
346*4882a593Smuzhiyun printf("start %ld end %ld\n", (long)start, (long)end);
347*4882a593Smuzhiyun if (end > start) {
348*4882a593Smuzhiyun printf("%.2f fps\n", ((double)x) / (end-start));
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun #endif
352*4882a593Smuzhiyun
gr_flip()353*4882a593Smuzhiyun void gr_flip() {
354*4882a593Smuzhiyun gr_draw = gr_backend->flip(gr_backend);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
gr_init(void)357*4882a593Smuzhiyun int gr_init(void)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun gr_init_font();
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun gr_vt_fd = open("/dev/tty0", O_RDWR | O_SYNC);
362*4882a593Smuzhiyun if (gr_vt_fd < 0) {
363*4882a593Smuzhiyun // This is non-fatal; post-Cupcake kernels don't have tty0.
364*4882a593Smuzhiyun perror("can't open /dev/tty0");
365*4882a593Smuzhiyun } else if (ioctl(gr_vt_fd, KDSETMODE, (void*) KD_GRAPHICS)) {
366*4882a593Smuzhiyun // However, if we do open tty0, we expect the ioctl to work.
367*4882a593Smuzhiyun perror("failed KDSETMODE to KD_GRAPHICS on tty0");
368*4882a593Smuzhiyun gr_exit();
369*4882a593Smuzhiyun return -1;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun gr_backend = 0;//open_adf();
373*4882a593Smuzhiyun if (gr_backend) {
374*4882a593Smuzhiyun gr_draw = gr_backend->init(gr_backend);
375*4882a593Smuzhiyun if (!gr_draw) {
376*4882a593Smuzhiyun gr_backend->exit(gr_backend);
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!gr_draw) {
381*4882a593Smuzhiyun gr_backend = open_drm();
382*4882a593Smuzhiyun gr_draw = gr_backend->init(gr_backend);
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun #if 0
385*4882a593Smuzhiyun if (!gr_draw) {
386*4882a593Smuzhiyun gr_backend = open_fbdev();
387*4882a593Smuzhiyun gr_draw = gr_backend->init(gr_backend);
388*4882a593Smuzhiyun if (gr_draw == NULL) {
389*4882a593Smuzhiyun return -1;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun #endif
393*4882a593Smuzhiyun overscan_offset_x = gr_draw->width * overscan_percent / 100;
394*4882a593Smuzhiyun overscan_offset_y = gr_draw->height * overscan_percent / 100;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun gr_flip();
397*4882a593Smuzhiyun gr_flip();
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun return 0;
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun
gr_exit(void)402*4882a593Smuzhiyun void gr_exit(void)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun gr_backend->exit(gr_backend);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun ioctl(gr_vt_fd, KDSETMODE, (void*) KD_TEXT);
407*4882a593Smuzhiyun close(gr_vt_fd);
408*4882a593Smuzhiyun gr_vt_fd = -1;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
gr_fb_width(void)411*4882a593Smuzhiyun int gr_fb_width(void)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun return gr_draw->width - 2*overscan_offset_x;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
gr_fb_height(void)416*4882a593Smuzhiyun int gr_fb_height(void)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun return gr_draw->height - 2*overscan_offset_y;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
gr_fb_blank(bool blank)421*4882a593Smuzhiyun void gr_fb_blank(bool blank)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun gr_backend->blank(gr_backend, blank);
424*4882a593Smuzhiyun }
425