blob: bb96af1419f44fbd5c0ffe363aaf56348b438f85 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tao Bao0ecbd762017-01-16 21:16:58 -080017#include "graphics.h"
18
Tao Baoe8020f42017-02-03 09:30:07 -080019#include <stdio.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080020#include <stdlib.h>
Elliott Hughescd3c55a2015-01-29 20:50:08 -080021#include <string.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080022
Tao Bao557fa1f2017-02-07 12:51:00 -080023#include <memory>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080024
maxwen39624d42015-12-01 22:02:07 +010025#ifdef BOARD_USE_CUSTOM_RECOVERY_FONT
26#include BOARD_USE_CUSTOM_RECOVERY_FONT
27#else
Doug Zongker6fd59ac2013-03-06 15:01:11 -080028#include "font_10x18.h"
maxwen39624d42015-12-01 22:02:07 +010029#endif
30
Tao Bao557fa1f2017-02-07 12:51:00 -080031#include "graphics_adf.h"
32#include "graphics_drm.h"
33#include "graphics_fbdev.h"
Ethan Yonker8373cfe2017-09-08 06:50:54 -050034#include "graphics_overlay.h"
Tao Bao0ecbd762017-01-16 21:16:58 -080035#include "minui/minui.h"
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080036
Doug Zongker16f97c32014-03-06 16:16:05 -080037static GRFont* gr_font = NULL;
Tao Bao557fa1f2017-02-07 12:51:00 -080038static MinuiBackend* gr_backend = nullptr;
Doug Zongker16f97c32014-03-06 16:16:05 -080039
Doug Zongkerc560a672012-12-18 16:31:27 -080040static int overscan_percent = OVERSCAN_PERCENT;
41static int overscan_offset_x = 0;
42static int overscan_offset_y = 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080043
Doug Zongker16f97c32014-03-06 16:16:05 -080044static unsigned char gr_current_r = 255;
45static unsigned char gr_current_g = 255;
46static unsigned char gr_current_b = 255;
47static unsigned char gr_current_a = 255;
Ethan Yonkere96182e2015-10-13 19:32:03 -050048static unsigned char rgb_555[2];
49static unsigned char gr_current_r5 = 31;
50static unsigned char gr_current_g5 = 63;
51static unsigned char gr_current_b5 = 31;
Doug Zongker16f97c32014-03-06 16:16:05 -080052
Doug Zongker5290f202014-03-11 13:22:04 -070053static GRSurface* gr_draw = NULL;
Doug Zongker16f97c32014-03-06 16:16:05 -080054
55static bool outside(int x, int y)
56{
57 return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height;
58}
Ethan Yonker39662b22017-05-23 08:34:02 -050059
60#ifdef TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080061int gr_measure(const char *s)
62{
Ethan Yonker84d61ce2017-05-10 16:11:35 -050063 return gr_font->char_width * strlen(s);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080064}
65
Dima Zavin3c7f00e2011-08-30 11:58:24 -070066void gr_font_size(int *x, int *y)
67{
Ethan Yonker84d61ce2017-05-10 16:11:35 -050068 *x = gr_font->char_width;
69 *y = gr_font->char_height;
Dima Zavin3c7f00e2011-08-30 11:58:24 -070070}
Ethan Yonker84d61ce2017-05-10 16:11:35 -050071#else // TW_USE_MINUI_CUSTOM_FONTS
Damien Bargiacchi35fff612016-08-11 15:57:03 -070072const GRFont* gr_sys_font()
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080073{
Damien Bargiacchi35fff612016-08-11 15:57:03 -070074 return gr_font;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080075}
76
Damien Bargiacchi35fff612016-08-11 15:57:03 -070077int gr_measure(const GRFont* font, const char *s)
Dima Zavin3c7f00e2011-08-30 11:58:24 -070078{
Damien Bargiacchi35fff612016-08-11 15:57:03 -070079 return font->char_width * strlen(s);
80}
81
82void gr_font_size(const GRFont* font, int *x, int *y)
83{
84 *x = font->char_width;
85 *y = font->char_height;
Dima Zavin3c7f00e2011-08-30 11:58:24 -070086}
Ethan Yonker39662b22017-05-23 08:34:02 -050087#endif // TW_NO_MINUI_CUSTOM_FONTS
Dima Zavin3c7f00e2011-08-30 11:58:24 -070088
Ethan Yonkere96182e2015-10-13 19:32:03 -050089void blend_16bpp(unsigned char* px, unsigned r5, unsigned g5, unsigned b5, unsigned char a)
90{
91 unsigned char orig[2];
92 orig[0] = px[0];
93 orig[1] = px[1];
94
95 /* This code is a little easier to read
96 unsigned oldred = (orig[1] >> 3);
97 unsigned oldgreen = (((orig[0] >> 5) << 3) + (orig[1] & 0x7));
98 unsigned oldblue = (orig[0] & 0x1F);
99
100 unsigned newred = (oldred * (255-a) + r5 * a) / 255;
101 unsigned newgreen = (oldgreen * (255-a) + g5 * a) / 255;
102 unsigned newblue = (oldblue * (255-a) + b5 * a) / 255;
103 */
104
105 unsigned newred = ((orig[1] >> 3) * (255-a) + r5 * a) / 255;
106 unsigned newgreen = ((((orig[0] >> 5) << 3) + (orig[1] & 0x7)) * (255-a) + g5 * a) / 255;
107 unsigned newblue = ((orig[0] & 0x1F) * (255-a) + b5 * a) / 255;
108
109 *px++ = (newgreen << 5) + (newblue);
110 *px++ = (newred << 3) + (newgreen >> 3);
111}
112
Doug Zongker16f97c32014-03-06 16:16:05 -0800113static void text_blend(unsigned char* src_p, int src_row_bytes,
114 unsigned char* dst_p, int dst_row_bytes,
115 int width, int height)
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800116{
Elliott Hughes01a4d082015-03-24 15:21:48 -0700117 for (int j = 0; j < height; ++j) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800118 unsigned char* sx = src_p;
119 unsigned char* px = dst_p;
Elliott Hughes01a4d082015-03-24 15:21:48 -0700120 for (int i = 0; i < width; ++i) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800121 unsigned char a = *sx++;
122 if (gr_current_a < 255) a = ((int)a * gr_current_a) / 255;
123 if (a == 255) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500124 if (gr_draw->pixel_bytes == 2) {
125 *px++ = rgb_555[0];
126 *px++ = rgb_555[1];
127 } else {
128 *px++ = gr_current_r;
129 *px++ = gr_current_g;
130 *px++ = gr_current_b;
131 px++;
132 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800133 } else if (a > 0) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500134 if (gr_draw->pixel_bytes == 2) {
135 blend_16bpp(px, gr_current_r5, gr_current_g5, gr_current_b5, a);
136 px += gr_draw->pixel_bytes;
137 } else {
138 *px = (*px * (255-a) + gr_current_r * a) / 255;
139 ++px;
140 *px = (*px * (255-a) + gr_current_g * a) / 255;
141 ++px;
142 *px = (*px * (255-a) + gr_current_b * a) / 255;
143 ++px;
144 ++px;
145 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800146 } else {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500147 px += gr_draw->pixel_bytes;
Doug Zongker16f97c32014-03-06 16:16:05 -0800148 }
149 }
150 src_p += src_row_bytes;
151 dst_p += dst_row_bytes;
152 }
153}
154
Ethan Yonker39662b22017-05-23 08:34:02 -0500155#ifdef TW_NO_MINUI_CUSTOM_FONTS
Elliott Hughes8fd86d72015-04-13 14:36:02 -0700156void gr_text(int x, int y, const char *s, bool bold)
Doug Zongker16f97c32014-03-06 16:16:05 -0800157{
Elliott Hughes01a4d082015-03-24 15:21:48 -0700158 GRFont* font = gr_font;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800159
Elliott Hughes01a4d082015-03-24 15:21:48 -0700160 if (!font->texture || gr_current_a == 0) return;
Doug Zongker55a36ac2013-03-04 15:49:02 -0800161
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500162 bold = bold && (font->texture->height != font->char_height);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800163
Doug Zongkerc560a672012-12-18 16:31:27 -0800164 x += overscan_offset_x;
165 y += overscan_offset_y;
166
Elliott Hughes01a4d082015-03-24 15:21:48 -0700167 unsigned char ch;
168 while ((ch = *s++)) {
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500169 if (outside(x, y) || outside(x+font->char_width-1, y+font->char_height-1)) break;
Doug Zongker16f97c32014-03-06 16:16:05 -0800170
Elliott Hughes01a4d082015-03-24 15:21:48 -0700171 if (ch < ' ' || ch > '~') {
172 ch = '?';
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800173 }
Elliott Hughes01a4d082015-03-24 15:21:48 -0700174
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500175 unsigned char* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
176 (bold ? font->char_height * font->texture->row_bytes : 0);
Elliott Hughes01a4d082015-03-24 15:21:48 -0700177 unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
178
179 text_blend(src_p, font->texture->row_bytes,
180 dst_p, gr_draw->row_bytes,
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500181 font->char_width, font->char_height);
Elliott Hughes01a4d082015-03-24 15:21:48 -0700182
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500183 x += font->char_width;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800184 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800185}
Ethan Yonker39662b22017-05-23 08:34:02 -0500186#else //TW_NO_MINUI_CUSTOM_FONTS
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700187void gr_text(const GRFont* font, int x, int y, const char *s, bool bold)
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800188{
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800189 if (!font->texture || gr_current_a == 0) return;
190
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700191 bold = bold && (font->texture->height != font->char_height);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800192
193 x += overscan_offset_x;
194 y += overscan_offset_y;
195
196 unsigned char ch;
197 while ((ch = *s++)) {
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700198 if (outside(x, y) || outside(x+font->char_width-1, y+font->char_height-1)) break;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800199
200 if (ch < ' ' || ch > '~') {
201 ch = '?';
202 }
203
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700204 unsigned char* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
205 (bold ? font->char_height * font->texture->row_bytes : 0);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800206 unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
207
208 text_blend(src_p, font->texture->row_bytes,
209 dst_p, gr_draw->row_bytes,
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700210 font->char_width, font->char_height);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800211
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700212 x += font->char_width;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800213 }
214}
Ethan Yonker39662b22017-05-23 08:34:02 -0500215#endif //TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800216
Doug Zongker16f97c32014-03-06 16:16:05 -0800217void gr_texticon(int x, int y, GRSurface* icon) {
218 if (icon == NULL) return;
219
220 if (icon->pixel_bytes != 1) {
221 printf("gr_texticon: source has wrong format\n");
Doug Zongker52eeea4f2012-09-04 14:28:25 -0700222 return;
223 }
Doug Zongker02ec6b82012-08-22 17:26:40 -0700224
Doug Zongkerc560a672012-12-18 16:31:27 -0800225 x += overscan_offset_x;
226 y += overscan_offset_y;
227
Doug Zongker16f97c32014-03-06 16:16:05 -0800228 if (outside(x, y) || outside(x+icon->width-1, y+icon->height-1)) return;
Doug Zongker02ec6b82012-08-22 17:26:40 -0700229
Doug Zongker16f97c32014-03-06 16:16:05 -0800230 unsigned char* src_p = icon->data;
231 unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
Doug Zongker02ec6b82012-08-22 17:26:40 -0700232
Doug Zongker16f97c32014-03-06 16:16:05 -0800233 text_blend(src_p, icon->row_bytes,
234 dst_p, gr_draw->row_bytes,
235 icon->width, icon->height);
236}
237
Ethan Yonkere96182e2015-10-13 19:32:03 -0500238void gr_convert_rgb_555()
239{
240 gr_current_r5 = (((gr_current_r & 0xFF) * 0x1F) + 0x7F) / 0xFF;
241 gr_current_g5 = (((gr_current_g & 0xFF) * 0x3F) + 0x7F) / 0xFF;
242 gr_current_b5 = (((gr_current_b & 0xFF) * 0x1F) + 0x7F) / 0xFF;
243
244 rgb_555[0] = (gr_current_g5 << 5) + (gr_current_b5);
245 rgb_555[1] = (gr_current_r5 << 3) + (gr_current_g5 >> 3);
246}
247
Doug Zongker16f97c32014-03-06 16:16:05 -0800248void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
249{
Tony Kuofd778e32015-02-05 21:25:56 +0800250#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
251 gr_current_r = b;
252 gr_current_g = g;
253 gr_current_b = r;
254 gr_current_a = a;
255#else
Doug Zongker16f97c32014-03-06 16:16:05 -0800256 gr_current_r = r;
257 gr_current_g = g;
258 gr_current_b = b;
259 gr_current_a = a;
Tony Kuofd778e32015-02-05 21:25:56 +0800260#endif
Ethan Yonkere96182e2015-10-13 19:32:03 -0500261 if (gr_draw->pixel_bytes == 2) {
262 gr_convert_rgb_555();
263 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800264}
265
266void gr_clear()
267{
Ethan Yonkere96182e2015-10-13 19:32:03 -0500268 if (gr_draw->pixel_bytes == 2) {
269 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
270 return;
271 }
272
273 // This code only works on 32bpp devices
Elliott Hughes01a4d082015-03-24 15:21:48 -0700274 if (gr_current_r == gr_current_g && gr_current_r == gr_current_b) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800275 memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes);
276 } else {
Doug Zongker16f97c32014-03-06 16:16:05 -0800277 unsigned char* px = gr_draw->data;
Elliott Hughes01a4d082015-03-24 15:21:48 -0700278 for (int y = 0; y < gr_draw->height; ++y) {
279 for (int x = 0; x < gr_draw->width; ++x) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800280 *px++ = gr_current_r;
281 *px++ = gr_current_g;
282 *px++ = gr_current_b;
283 px++;
284 }
285 px += gr_draw->row_bytes - (gr_draw->width * gr_draw->pixel_bytes);
286 }
287 }
Doug Zongker02ec6b82012-08-22 17:26:40 -0700288}
289
Doug Zongkerc560a672012-12-18 16:31:27 -0800290void gr_fill(int x1, int y1, int x2, int y2)
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800291{
Doug Zongkerc560a672012-12-18 16:31:27 -0800292 x1 += overscan_offset_x;
293 y1 += overscan_offset_y;
294
295 x2 += overscan_offset_x;
296 y2 += overscan_offset_y;
297
Doug Zongker16f97c32014-03-06 16:16:05 -0800298 if (outside(x1, y1) || outside(x2-1, y2-1)) return;
299
300 unsigned char* p = gr_draw->data + y1 * gr_draw->row_bytes + x1 * gr_draw->pixel_bytes;
301 if (gr_current_a == 255) {
302 int x, y;
303 for (y = y1; y < y2; ++y) {
304 unsigned char* px = p;
305 for (x = x1; x < x2; ++x) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500306 if (gr_draw->pixel_bytes == 2) {
307 *px++ = rgb_555[0];
308 *px++ = rgb_555[1];
309 } else {
310 *px++ = gr_current_r;
311 *px++ = gr_current_g;
312 *px++ = gr_current_b;
313 px++;
314 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800315 }
316 p += gr_draw->row_bytes;
317 }
318 } else if (gr_current_a > 0) {
319 int x, y;
320 for (y = y1; y < y2; ++y) {
321 unsigned char* px = p;
322 for (x = x1; x < x2; ++x) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500323 if (gr_draw->pixel_bytes == 2) {
324 blend_16bpp(px, gr_current_r5, gr_current_g5, gr_current_b5, gr_current_a);
325 px += gr_draw->row_bytes;
326 } else {
327 *px = (*px * (255-gr_current_a) + gr_current_r * gr_current_a) / 255;
328 ++px;
329 *px = (*px * (255-gr_current_a) + gr_current_g * gr_current_a) / 255;
330 ++px;
331 *px = (*px * (255-gr_current_a) + gr_current_b * gr_current_a) / 255;
332 ++px;
333 ++px;
334 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800335 }
336 p += gr_draw->row_bytes;
337 }
338 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800339}
340
Ethan Yonkere96182e2015-10-13 19:32:03 -0500341void gr_blit_32to16(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
342 dx += overscan_offset_x;
343 dy += overscan_offset_y;
344
345 if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return;
346
347 unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes;
348 unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes;
349
350 int i, j;
351 for (i = 0; i < h; ++i) {
352 unsigned char* spx = src_p;
353 unsigned char* dpx = dst_p;
354
355 for (j = 0; j < w; ++j) {
356 unsigned a = spx[3];
357
358 if (a == 0) {
359 spx += source->pixel_bytes;
360 dpx += gr_draw->pixel_bytes;
361 } else {
362 unsigned r5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF;
363 unsigned g5 = (((*spx++ & 0xFF) * 0x3F) + 0x7F) / 0xFF;
364 unsigned b5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF;
365 spx++;
366 if (a == 255) {
367 *dpx++ = (g5 << 5) + (b5);
368 *dpx++ = (r5 << 3) + (g5 >> 3);
369 } else {
370 blend_16bpp(dpx, r5, g5, b5, a);
371 spx += source->pixel_bytes;
372 }
373 }
374 }
375 src_p += source->row_bytes;
376 dst_p += gr_draw->row_bytes;
377 }
378}
379
Doug Zongker16f97c32014-03-06 16:16:05 -0800380void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
381 if (source == NULL) return;
382
383 if (gr_draw->pixel_bytes != source->pixel_bytes) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500384 if (gr_draw->pixel_bytes == 2 && source->pixel_bytes == 4) {
385 gr_blit_32to16(source, sx, sy, w, h, dx, dy);
386 return;
387 } else {
388 printf("gr_blit: source has wrong format\n");
389 return;
390 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800391 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800392
Doug Zongkerc560a672012-12-18 16:31:27 -0800393 dx += overscan_offset_x;
394 dy += overscan_offset_y;
395
Doug Zongker16f97c32014-03-06 16:16:05 -0800396 if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return;
397
398 unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes;
399 unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes;
400
401 int i;
402 for (i = 0; i < h; ++i) {
403 memcpy(dst_p, src_p, w * source->pixel_bytes);
404 src_p += source->row_bytes;
405 dst_p += gr_draw->row_bytes;
406 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800407}
408
Doug Zongker16f97c32014-03-06 16:16:05 -0800409unsigned int gr_get_width(GRSurface* surface) {
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800410 if (surface == NULL) {
411 return 0;
412 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800413 return surface->width;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800414}
415
Doug Zongker16f97c32014-03-06 16:16:05 -0800416unsigned int gr_get_height(GRSurface* surface) {
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800417 if (surface == NULL) {
418 return 0;
419 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800420 return surface->height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800421}
422
Ethan Yonker39662b22017-05-23 08:34:02 -0500423#ifdef TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800424static void gr_init_font(void)
425{
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700426 gr_font = reinterpret_cast<GRFont*>(calloc(sizeof(*gr_font), 1));
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800427
Doug Zongkera418aa72014-03-17 12:10:02 -0700428 int res = res_create_alpha_surface("font", &(gr_font->texture));
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800429 if (res == 0) {
430 // The font image should be a 96x2 array of character images. The
431 // columns are the printable ASCII characters 0x20 - 0x7f. The
432 // top row is regular text; the bottom row is bold.
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500433 gr_font->char_width = gr_font->texture->width / 96;
434 gr_font->char_height = gr_font->texture->height / 2;
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800435 } else {
Doug Zongker55a36ac2013-03-04 15:49:02 -0800436 printf("failed to read font: res=%d\n", res);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800437
438 // fall back to the compiled-in font.
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700439 gr_font->texture = reinterpret_cast<GRSurface*>(malloc(sizeof(*gr_font->texture)));
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800440 gr_font->texture->width = font.width;
441 gr_font->texture->height = font.height;
Doug Zongker16f97c32014-03-06 16:16:05 -0800442 gr_font->texture->row_bytes = font.width;
443 gr_font->texture->pixel_bytes = 1;
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800444
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700445 unsigned char* bits = reinterpret_cast<unsigned char*>(malloc(font.width * font.height));
446 gr_font->texture->data = reinterpret_cast<unsigned char*>(bits);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800447
448 unsigned char data;
449 unsigned char* in = font.rundata;
450 while((data = *in++)) {
451 memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
452 bits += (data & 0x7f);
453 }
454
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500455 gr_font->char_width = font.char_width;
456 gr_font->char_height = font.char_height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800457 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800458}
459
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500460void gr_set_font(__attribute__ ((unused))const char* name) {
461 //this cm function is made to change font. Don't care, just init the font:
462 gr_init_font();
463 return;
464}
Ethan Yonker39662b22017-05-23 08:34:02 -0500465#else // TW_NO_MINUI_CUSTOM_FONTS
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700466int gr_init_font(const char* name, GRFont** dest) {
Rahul Chaudhry4f7faac2016-11-08 16:06:13 -0800467 GRFont* font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700468 if (font == nullptr) {
469 return -1;
470 }
471
472 int res = res_create_alpha_surface(name, &(font->texture));
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700473 if (res < 0) {
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700474 free(font);
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700475 return res;
476 }
477
478 // The font image should be a 96x2 array of character images. The
479 // columns are the printable ASCII characters 0x20 - 0x7f. The
480 // top row is regular text; the bottom row is bold.
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700481 font->char_width = font->texture->width / 96;
482 font->char_height = font->texture->height / 2;
483
484 *dest = font;
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700485
486 return 0;
487}
488
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800489static void gr_init_font(void)
490{
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700491 int res = gr_init_font("font", &gr_font);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800492 if (res == 0) {
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700493 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800494 }
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700495
496 printf("failed to read font: res=%d\n", res);
497
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700498
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700499 // fall back to the compiled-in font.
Rahul Chaudhry4f7faac2016-11-08 16:06:13 -0800500 gr_font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
501 gr_font->texture = static_cast<GRSurface*>(malloc(sizeof(*gr_font->texture)));
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700502 gr_font->texture->width = font.width;
503 gr_font->texture->height = font.height;
504 gr_font->texture->row_bytes = font.width;
505 gr_font->texture->pixel_bytes = 1;
506
Rahul Chaudhry4f7faac2016-11-08 16:06:13 -0800507 unsigned char* bits = static_cast<unsigned char*>(malloc(font.width * font.height));
Rahul Chaudhry1cf93f52016-11-08 16:35:22 -0800508 gr_font->texture->data = bits;
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700509
510 unsigned char data;
511 unsigned char* in = font.rundata;
512 while((data = *in++)) {
513 memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
514 bits += (data & 0x7f);
515 }
516
517 gr_font->char_width = font.char_width;
518 gr_font->char_height = font.char_height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800519}
Ethan Yonker39662b22017-05-23 08:34:02 -0500520#endif // TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800521
Doug Zongker5290f202014-03-11 13:22:04 -0700522void gr_flip() {
Tao Bao557fa1f2017-02-07 12:51:00 -0800523 gr_draw = gr_backend->Flip();
Doug Zongker5290f202014-03-11 13:22:04 -0700524}
525
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800526int gr_init(void)
527{
Tao Bao557fa1f2017-02-07 12:51:00 -0800528 gr_init_font();
Doug Zongker16f97c32014-03-06 16:16:05 -0800529
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500530 auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendOverlay>() };
Tao Bao557fa1f2017-02-07 12:51:00 -0800531 gr_draw = backend->Init();
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800532
Ethan Yonkerb386f712017-01-20 14:30:28 -0600533#ifdef MSM_BSP
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500534 if (gr_draw) {
535 printf("Using overlay graphics.\n");
Ethan Yonkera59da092015-10-13 19:35:05 -0500536 }
Ethan Yonkerb386f712017-01-20 14:30:28 -0600537#endif
Ethan Yonkera59da092015-10-13 19:35:05 -0500538
539#ifndef MSM_BSP
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500540 if (!gr_draw) {
541 backend = std::make_unique<MinuiBackendAdf>();
542 gr_draw = backend->Init();
543 if (gr_draw)
544 printf("Using adf graphics.\n");
Greg Hackmann41909dd2014-04-25 10:39:50 -0700545 }
Ethan Yonkera59da092015-10-13 19:35:05 -0500546#else
547 printf("Skipping adf graphics because TW_TARGET_USES_QCOM_BSP := true\n");
548#endif
Greg Hackmann41909dd2014-04-25 10:39:50 -0700549
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500550 if (!gr_draw) {
551 backend = std::make_unique<MinuiBackendDrm>();
552 gr_draw = backend->Init();
Ethan Yonkera59da092015-10-13 19:35:05 -0500553 if (gr_draw)
554 printf("Using drm graphics.\n");
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700555 }
556
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500557 if (!gr_draw) {
558 backend = std::make_unique<MinuiBackendFbdev>();
559 gr_draw = backend->Init();
560 if (gr_draw)
Ethan Yonkera59da092015-10-13 19:35:05 -0500561 printf("Using fbdev graphics.\n");
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800562 }
563
Tao Bao557fa1f2017-02-07 12:51:00 -0800564 if (!gr_draw) {
565 return -1;
566 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800567
Tao Bao557fa1f2017-02-07 12:51:00 -0800568 gr_backend = backend.release();
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800569
Tao Bao557fa1f2017-02-07 12:51:00 -0800570 overscan_offset_x = gr_draw->width * overscan_percent / 100;
571 overscan_offset_y = gr_draw->height * overscan_percent / 100;
572
573 gr_flip();
574 gr_flip();
575
576 return 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800577}
578
Tao Bao557fa1f2017-02-07 12:51:00 -0800579void gr_exit() {
580 delete gr_backend;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800581}
582
Tao Bao557fa1f2017-02-07 12:51:00 -0800583int gr_fb_width() {
584 return gr_draw->width - 2 * overscan_offset_x;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800585}
586
Tao Bao557fa1f2017-02-07 12:51:00 -0800587int gr_fb_height() {
588 return gr_draw->height - 2 * overscan_offset_y;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800589}
Dima Zavin4daf48a2011-08-30 11:59:20 -0700590
Tao Bao557fa1f2017-02-07 12:51:00 -0800591void gr_fb_blank(bool blank) {
592 gr_backend->Blank(blank);
Dima Zavin4daf48a2011-08-30 11:59:20 -0700593}