blob: f3380aaa094808b1836b5354d0b676a8fe94375e [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
Luke Song846012f2017-09-13 15:56:16 -070019#include <stdint.h>
Tao Baoe8020f42017-02-03 09:30:07 -080020#include <stdio.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080021#include <stdlib.h>
Elliott Hughescd3c55a2015-01-29 20:50:08 -080022#include <string.h>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080023
Tao Bao557fa1f2017-02-07 12:51:00 -080024#include <memory>
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080025
maxwen39624d42015-12-01 22:02:07 +010026#ifdef BOARD_USE_CUSTOM_RECOVERY_FONT
27#include BOARD_USE_CUSTOM_RECOVERY_FONT
28#else
Doug Zongker6fd59ac2013-03-06 15:01:11 -080029#include "font_10x18.h"
maxwen39624d42015-12-01 22:02:07 +010030#endif
31
Andreas Schneider58d68e52017-11-02 17:54:36 +010032#ifndef MSM_BSP
Tao Bao557fa1f2017-02-07 12:51:00 -080033#include "graphics_adf.h"
Andreas Schneider58d68e52017-11-02 17:54:36 +010034#endif
Tao Bao557fa1f2017-02-07 12:51:00 -080035#include "graphics_drm.h"
36#include "graphics_fbdev.h"
Ethan Yonker8373cfe2017-09-08 06:50:54 -050037#include "graphics_overlay.h"
Tao Bao0ecbd762017-01-16 21:16:58 -080038#include "minui/minui.h"
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080039
Doug Zongker16f97c32014-03-06 16:16:05 -080040static GRFont* gr_font = NULL;
Tao Bao557fa1f2017-02-07 12:51:00 -080041static MinuiBackend* gr_backend = nullptr;
Doug Zongker16f97c32014-03-06 16:16:05 -080042
Doug Zongkerc560a672012-12-18 16:31:27 -080043static int overscan_percent = OVERSCAN_PERCENT;
44static int overscan_offset_x = 0;
45static int overscan_offset_y = 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080046
Ethan Yonker58f21322018-08-24 11:17:36 -050047#ifdef TW_NO_MINUI_CUSTOM_FONTS
Doug Zongker16f97c32014-03-06 16:16:05 -080048static unsigned char gr_current_r = 255;
49static unsigned char gr_current_g = 255;
50static unsigned char gr_current_b = 255;
Ethan Yonker58f21322018-08-24 11:17:36 -050051#endif
Doug Zongker16f97c32014-03-06 16:16:05 -080052static unsigned char gr_current_a = 255;
Ethan Yonkere96182e2015-10-13 19:32:03 -050053static unsigned char rgb_555[2];
54static unsigned char gr_current_r5 = 31;
55static unsigned char gr_current_g5 = 63;
56static unsigned char gr_current_b5 = 31;
Doug Zongker16f97c32014-03-06 16:16:05 -080057
Luke Song846012f2017-09-13 15:56:16 -070058static uint32_t gr_current = ~0;
59static constexpr uint32_t alpha_mask = 0xff000000;
Doug Zongker16f97c32014-03-06 16:16:05 -080060
Doug Zongker16f97c32014-03-06 16:16:05 -080061static GRSurface* gr_draw = NULL;
Luke Song846012f2017-09-13 15:56:16 -070062static GRRotation rotation = ROTATION_NONE;
Doug Zongker16f97c32014-03-06 16:16:05 -080063
Luke Song846012f2017-09-13 15:56:16 -070064static bool outside(int x, int y) {
65 return x < 0 || x >= (rotation % 2 ? gr_draw->height : gr_draw->width) || y < 0 ||
66 y >= (rotation % 2 ? gr_draw->width : gr_draw->height);
Doug Zongker16f97c32014-03-06 16:16:05 -080067}
Ethan Yonker39662b22017-05-23 08:34:02 -050068
69#ifdef TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080070int gr_measure(const char *s)
71{
Ethan Yonker84d61ce2017-05-10 16:11:35 -050072 return gr_font->char_width * strlen(s);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080073}
74
Dima Zavin3c7f00e2011-08-30 11:58:24 -070075void gr_font_size(int *x, int *y)
76{
Ethan Yonker84d61ce2017-05-10 16:11:35 -050077 *x = gr_font->char_width;
78 *y = gr_font->char_height;
Dima Zavin3c7f00e2011-08-30 11:58:24 -070079}
Ethan Yonker84d61ce2017-05-10 16:11:35 -050080#else // TW_USE_MINUI_CUSTOM_FONTS
Luke Song846012f2017-09-13 15:56:16 -070081const GRFont* gr_sys_font() {
82 return gr_font;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080083}
84
Luke Song846012f2017-09-13 15:56:16 -070085int gr_measure(const GRFont* font, const char* s) {
86 return font->char_width * strlen(s);
Damien Bargiacchi35fff612016-08-11 15:57:03 -070087}
88
Luke Song846012f2017-09-13 15:56:16 -070089void gr_font_size(const GRFont* font, int* x, int* y) {
90 *x = font->char_width;
91 *y = font->char_height;
Dima Zavin3c7f00e2011-08-30 11:58:24 -070092}
Ethan Yonker39662b22017-05-23 08:34:02 -050093#endif // TW_NO_MINUI_CUSTOM_FONTS
Dima Zavin3c7f00e2011-08-30 11:58:24 -070094
Ethan Yonkere96182e2015-10-13 19:32:03 -050095void blend_16bpp(unsigned char* px, unsigned r5, unsigned g5, unsigned b5, unsigned char a)
96{
97 unsigned char orig[2];
98 orig[0] = px[0];
99 orig[1] = px[1];
100
101 /* This code is a little easier to read
102 unsigned oldred = (orig[1] >> 3);
103 unsigned oldgreen = (((orig[0] >> 5) << 3) + (orig[1] & 0x7));
104 unsigned oldblue = (orig[0] & 0x1F);
105
106 unsigned newred = (oldred * (255-a) + r5 * a) / 255;
107 unsigned newgreen = (oldgreen * (255-a) + g5 * a) / 255;
108 unsigned newblue = (oldblue * (255-a) + b5 * a) / 255;
109 */
110
111 unsigned newred = ((orig[1] >> 3) * (255-a) + r5 * a) / 255;
112 unsigned newgreen = ((((orig[0] >> 5) << 3) + (orig[1] & 0x7)) * (255-a) + g5 * a) / 255;
113 unsigned newblue = ((orig[0] & 0x1F) * (255-a) + b5 * a) / 255;
114
115 *px++ = (newgreen << 5) + (newblue);
116 *px++ = (newred << 3) + (newgreen >> 3);
117}
118
Ethan Yonker58f21322018-08-24 11:17:36 -0500119#ifdef TW_NO_MINUI_CUSTOM_FONTS
120static void text_blend_old(unsigned char* src_p, int src_row_bytes,
Doug Zongker16f97c32014-03-06 16:16:05 -0800121 unsigned char* dst_p, int dst_row_bytes,
122 int width, int height)
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800123{
Elliott Hughes01a4d082015-03-24 15:21:48 -0700124 for (int j = 0; j < height; ++j) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800125 unsigned char* sx = src_p;
126 unsigned char* px = dst_p;
Elliott Hughes01a4d082015-03-24 15:21:48 -0700127 for (int i = 0; i < width; ++i) {
Doug Zongker16f97c32014-03-06 16:16:05 -0800128 unsigned char a = *sx++;
129 if (gr_current_a < 255) a = ((int)a * gr_current_a) / 255;
130 if (a == 255) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500131 if (gr_draw->pixel_bytes == 2) {
132 *px++ = rgb_555[0];
133 *px++ = rgb_555[1];
134 } else {
135 *px++ = gr_current_r;
136 *px++ = gr_current_g;
137 *px++ = gr_current_b;
138 px++;
139 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800140 } else if (a > 0) {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500141 if (gr_draw->pixel_bytes == 2) {
142 blend_16bpp(px, gr_current_r5, gr_current_g5, gr_current_b5, a);
143 px += gr_draw->pixel_bytes;
144 } else {
145 *px = (*px * (255-a) + gr_current_r * a) / 255;
146 ++px;
147 *px = (*px * (255-a) + gr_current_g * a) / 255;
148 ++px;
149 *px = (*px * (255-a) + gr_current_b * a) / 255;
150 ++px;
151 ++px;
152 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800153 } else {
Ethan Yonkere96182e2015-10-13 19:32:03 -0500154 px += gr_draw->pixel_bytes;
Doug Zongker16f97c32014-03-06 16:16:05 -0800155 }
156 }
157 src_p += src_row_bytes;
158 dst_p += dst_row_bytes;
159 }
160}
Ethan Yonker58f21322018-08-24 11:17:36 -0500161#endif // TW_NO_MINUI_CUSTOM_FONTS
162
163// Blends gr_current onto pix value, assumes alpha as most significant byte.
164static inline uint16_t pixel_blend16(uint8_t a, uint16_t pix) {
165 unsigned char orig[2];
166 orig[0] = (pix & 0xFF00) >> 8;
167 orig[1] = pix & 0x00FF;
168
169 /* This code is a little easier to read
170 unsigned oldred = (orig[1] >> 3);
171 unsigned oldgreen = (((orig[0] >> 5) << 3) + (orig[1] & 0x7));
172 unsigned oldblue = (orig[0] & 0x1F);
173
174 unsigned newred = (oldred * (255-a) + r5 * a) / 255;
175 unsigned newgreen = (oldgreen * (255-a) + g5 * a) / 255;
176 unsigned newblue = (oldblue * (255-a) + b5 * a) / 255;
177 */
178
179 unsigned newred = ((orig[1] >> 3) * (255-a) + gr_current_r5 * a) / 255;
180 unsigned newgreen = ((((orig[0] >> 5) << 3) + (orig[1] & 0x7)) * (255-a) + gr_current_g5 * a) / 255;
181 unsigned newblue = ((orig[0] & 0x1F) * (255-a) + gr_current_b5 * a) / 255;
182
183 uint16_t newpix = (newred << 10) + (newgreen << 5) + newblue;
184 return newpix;
185}
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800186
Luke Song846012f2017-09-13 15:56:16 -0700187// Blends gr_current onto pix value, assumes alpha as most significant byte.
188static inline uint32_t pixel_blend(uint8_t alpha, uint32_t pix) {
189 if (alpha == 255) return gr_current;
190 if (alpha == 0) return pix;
191 uint32_t pix_r = pix & 0xff;
192 uint32_t pix_g = pix & 0xff00;
193 uint32_t pix_b = pix & 0xff0000;
194 uint32_t cur_r = gr_current & 0xff;
195 uint32_t cur_g = gr_current & 0xff00;
196 uint32_t cur_b = gr_current & 0xff0000;
197
198 uint32_t out_r = (pix_r * (255 - alpha) + cur_r * alpha) / 255;
199 uint32_t out_g = (pix_g * (255 - alpha) + cur_g * alpha) / 255;
200 uint32_t out_b = (pix_b * (255 - alpha) + cur_b * alpha) / 255;
201
202 return (out_r & 0xff) | (out_g & 0xff00) | (out_b & 0xff0000) | (gr_current & 0xff000000);
203}
204
205// increments pixel pointer right, with current rotation.
Ethan Yonker58f21322018-08-24 11:17:36 -0500206static void incr_x16(uint16_t** p, int row_pixels) {
207 if (rotation % 2) {
208 *p = *p + (rotation == 1 ? 1 : -1) * row_pixels;
209 } else {
210 *p = *p + (rotation ? -1 : 1);
211 }
212}
213
214// increments pixel pointer down, with current rotation.
215static void incr_y16(uint16_t** p, int row_pixels) {
216 if (rotation % 2) {
217 *p = *p + (rotation == 1 ? -1 : 1);
218 } else {
219 *p = *p + (rotation ? -1 : 1) * row_pixels;
220 }
221}
222
223// increments pixel pointer right, with current rotation.
Luke Song846012f2017-09-13 15:56:16 -0700224static void incr_x(uint32_t** p, int row_pixels) {
225 if (rotation % 2) {
226 *p = *p + (rotation == 1 ? 1 : -1) * row_pixels;
227 } else {
228 *p = *p + (rotation ? -1 : 1);
229 }
230}
231
232// increments pixel pointer down, with current rotation.
233static void incr_y(uint32_t** p, int row_pixels) {
234 if (rotation % 2) {
235 *p = *p + (rotation == 1 ? -1 : 1);
236 } else {
237 *p = *p + (rotation ? -1 : 1) * row_pixels;
238 }
239}
240
241// returns pixel pointer at given coordinates with rotation adjustment.
Ethan Yonker58f21322018-08-24 11:17:36 -0500242static uint16_t* pixel_at16(GRSurface* surf, int x, int y, int row_pixels) {
243 switch (rotation) {
244 case ROTATION_NONE:
245 return reinterpret_cast<uint16_t*>(surf->data) + y * row_pixels + x;
246 case ROTATION_RIGHT:
247 return reinterpret_cast<uint16_t*>(surf->data) + x * row_pixels + (surf->width - y);
248 case ROTATION_DOWN:
249 return reinterpret_cast<uint16_t*>(surf->data) + (surf->height - 1 - y) * row_pixels +
250 (surf->width - 1 - x);
251 case ROTATION_LEFT:
252 return reinterpret_cast<uint16_t*>(surf->data) + (surf->height - 1 - x) * row_pixels + y;
253 default:
254 printf("invalid rotation %d", rotation);
255 }
256 return nullptr;
257}
258
259// returns pixel pointer at given coordinates with rotation adjustment.
Luke Song846012f2017-09-13 15:56:16 -0700260static uint32_t* pixel_at(GRSurface* surf, int x, int y, int row_pixels) {
261 switch (rotation) {
262 case ROTATION_NONE:
263 return reinterpret_cast<uint32_t*>(surf->data) + y * row_pixels + x;
264 case ROTATION_RIGHT:
265 return reinterpret_cast<uint32_t*>(surf->data) + x * row_pixels + (surf->width - y);
266 case ROTATION_DOWN:
267 return reinterpret_cast<uint32_t*>(surf->data) + (surf->height - 1 - y) * row_pixels +
268 (surf->width - 1 - x);
269 case ROTATION_LEFT:
270 return reinterpret_cast<uint32_t*>(surf->data) + (surf->height - 1 - x) * row_pixels + y;
271 default:
272 printf("invalid rotation %d", rotation);
273 }
274 return nullptr;
275}
276
Ethan Yonker58f21322018-08-24 11:17:36 -0500277static void text_blend16(uint8_t* src_p, int src_row_bytes, uint16_t* dst_p, int dst_row_pixels,
278 int width, int height) {
279 uint8_t alpha_current = static_cast<uint8_t>((alpha_mask & gr_current) >> 24);
280 for (int j = 0; j < height; ++j) {
281 uint8_t* sx = src_p;
282 uint16_t* px = dst_p;
283 for (int i = 0; i < width; ++i, incr_x16(&px, dst_row_pixels)) {
284 uint8_t a = *sx++;
285 if (alpha_current < 255) a = (static_cast<uint32_t>(a) * alpha_current) / 255;
286 *px = pixel_blend16(a, *px);
287 }
288 src_p += src_row_bytes;
289 incr_y16(&dst_p, dst_row_pixels);
290 }
291}
292
Luke Song846012f2017-09-13 15:56:16 -0700293static void text_blend(uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, int dst_row_pixels,
294 int width, int height) {
295 uint8_t alpha_current = static_cast<uint8_t>((alpha_mask & gr_current) >> 24);
296 for (int j = 0; j < height; ++j) {
297 uint8_t* sx = src_p;
298 uint32_t* px = dst_p;
299 for (int i = 0; i < width; ++i, incr_x(&px, dst_row_pixels)) {
300 uint8_t a = *sx++;
301 if (alpha_current < 255) a = (static_cast<uint32_t>(a) * alpha_current) / 255;
302 *px = pixel_blend(a, *px);
Doug Zongker16f97c32014-03-06 16:16:05 -0800303 }
Luke Song846012f2017-09-13 15:56:16 -0700304 src_p += src_row_bytes;
305 incr_y(&dst_p, dst_row_pixels);
306 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800307}
308
Doug Zongker16f97c32014-03-06 16:16:05 -0800309
Ethan Yonker39662b22017-05-23 08:34:02 -0500310#ifdef TW_NO_MINUI_CUSTOM_FONTS
Elliott Hughes8fd86d72015-04-13 14:36:02 -0700311void gr_text(int x, int y, const char *s, bool bold)
Doug Zongker16f97c32014-03-06 16:16:05 -0800312{
Elliott Hughes01a4d082015-03-24 15:21:48 -0700313 GRFont* font = gr_font;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800314
Elliott Hughes01a4d082015-03-24 15:21:48 -0700315 if (!font->texture || gr_current_a == 0) return;
Doug Zongker55a36ac2013-03-04 15:49:02 -0800316
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500317 bold = bold && (font->texture->height != font->char_height);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800318
Doug Zongkerc560a672012-12-18 16:31:27 -0800319 x += overscan_offset_x;
320 y += overscan_offset_y;
321
Elliott Hughes01a4d082015-03-24 15:21:48 -0700322 unsigned char ch;
323 while ((ch = *s++)) {
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500324 if (outside(x, y) || outside(x+font->char_width-1, y+font->char_height-1)) break;
Doug Zongker16f97c32014-03-06 16:16:05 -0800325
Elliott Hughes01a4d082015-03-24 15:21:48 -0700326 if (ch < ' ' || ch > '~') {
327 ch = '?';
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800328 }
Elliott Hughes01a4d082015-03-24 15:21:48 -0700329
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500330 unsigned char* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
331 (bold ? font->char_height * font->texture->row_bytes : 0);
Elliott Hughes01a4d082015-03-24 15:21:48 -0700332 unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes;
333
Ethan Yonker58f21322018-08-24 11:17:36 -0500334 text_blend_old(src_p, font->texture->row_bytes,
335 dst_p, gr_draw->row_bytes,
336 font->char_width, font->char_height);
Elliott Hughes01a4d082015-03-24 15:21:48 -0700337
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500338 x += font->char_width;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800339 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800340}
Ethan Yonker39662b22017-05-23 08:34:02 -0500341#else //TW_NO_MINUI_CUSTOM_FONTS
Luke Song846012f2017-09-13 15:56:16 -0700342void gr_text(const GRFont* font, int x, int y, const char* s, bool bold) {
343 if (!font || !font->texture || (gr_current & alpha_mask) == 0) return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800344
Luke Song846012f2017-09-13 15:56:16 -0700345 if (font->texture->pixel_bytes != 1) {
346 printf("gr_text: font has wrong format\n");
347 return;
348 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800349
Luke Song846012f2017-09-13 15:56:16 -0700350 bold = bold && (font->texture->height != font->char_height);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800351
Luke Song846012f2017-09-13 15:56:16 -0700352 x += overscan_offset_x;
353 y += overscan_offset_y;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800354
Luke Song846012f2017-09-13 15:56:16 -0700355 unsigned char ch;
356 while ((ch = *s++)) {
357 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 -0800358
Luke Song846012f2017-09-13 15:56:16 -0700359 if (ch < ' ' || ch > '~') {
360 ch = '?';
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800361 }
Luke Song846012f2017-09-13 15:56:16 -0700362
363 int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
Ethan Yonker58f21322018-08-24 11:17:36 -0500364
Luke Song846012f2017-09-13 15:56:16 -0700365 uint8_t* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
366 (bold ? font->char_height * font->texture->row_bytes : 0);
Ethan Yonker58f21322018-08-24 11:17:36 -0500367 if (gr_draw->pixel_bytes == 2) {
368 uint16_t* dst_p = pixel_at16(gr_draw, x, y, row_pixels);
369
370 text_blend16(src_p, font->texture->row_bytes, dst_p, row_pixels, font->char_width,
371 font->char_height);
372 } else { // not indenting AOSP original code
Luke Song846012f2017-09-13 15:56:16 -0700373 uint32_t* dst_p = pixel_at(gr_draw, x, y, row_pixels);
374
375 text_blend(src_p, font->texture->row_bytes, dst_p, row_pixels, font->char_width,
376 font->char_height);
Ethan Yonker58f21322018-08-24 11:17:36 -0500377 }
Luke Song846012f2017-09-13 15:56:16 -0700378 x += font->char_width;
379 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800380}
Ethan Yonker39662b22017-05-23 08:34:02 -0500381#endif //TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800382
Doug Zongker16f97c32014-03-06 16:16:05 -0800383void gr_texticon(int x, int y, GRSurface* icon) {
Luke Song846012f2017-09-13 15:56:16 -0700384 if (icon == NULL) return;
Doug Zongker16f97c32014-03-06 16:16:05 -0800385
Luke Song846012f2017-09-13 15:56:16 -0700386 if (icon->pixel_bytes != 1) {
387 printf("gr_texticon: source has wrong format\n");
388 return;
389 }
Doug Zongker02ec6b82012-08-22 17:26:40 -0700390
Luke Song846012f2017-09-13 15:56:16 -0700391 x += overscan_offset_x;
392 y += overscan_offset_y;
Doug Zongkerc560a672012-12-18 16:31:27 -0800393
Luke Song846012f2017-09-13 15:56:16 -0700394 if (outside(x, y) || outside(x + icon->width - 1, y + icon->height - 1)) return;
Doug Zongker02ec6b82012-08-22 17:26:40 -0700395
Luke Song846012f2017-09-13 15:56:16 -0700396 int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
397 uint8_t* src_p = icon->data;
Ethan Yonker58f21322018-08-24 11:17:36 -0500398 if (gr_draw->pixel_bytes == 2) {
399 uint16_t* dst_p = pixel_at16(gr_draw, x, y, row_pixels);
Doug Zongker02ec6b82012-08-22 17:26:40 -0700400
Ethan Yonker58f21322018-08-24 11:17:36 -0500401 text_blend16(src_p, icon->row_bytes, dst_p, row_pixels, icon->width, icon->height);
402 return;
403 }
Luke Song846012f2017-09-13 15:56:16 -0700404 uint32_t* dst_p = pixel_at(gr_draw, x, y, row_pixels);
Doug Zongker02ec6b82012-08-22 17:26:40 -0700405
Luke Song846012f2017-09-13 15:56:16 -0700406 text_blend(src_p, icon->row_bytes, dst_p, row_pixels, icon->width, icon->height);
Doug Zongker16f97c32014-03-06 16:16:05 -0800407}
408
Ethan Yonker58f21322018-08-24 11:17:36 -0500409void gr_convert_rgb_555(unsigned char r, unsigned char g, unsigned char b)
Ethan Yonkere96182e2015-10-13 19:32:03 -0500410{
Ethan Yonker58f21322018-08-24 11:17:36 -0500411 gr_current_r5 = (((r & 0xFF) * 0x1F) + 0x7F) / 0xFF;
412 gr_current_g5 = (((g & 0xFF) * 0x3F) + 0x7F) / 0xFF;
413 gr_current_b5 = (((b & 0xFF) * 0x1F) + 0x7F) / 0xFF;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500414
415 rgb_555[0] = (gr_current_g5 << 5) + (gr_current_b5);
416 rgb_555[1] = (gr_current_r5 << 3) + (gr_current_g5 >> 3);
417}
418
Luke Song846012f2017-09-13 15:56:16 -0700419void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
Ethan Yonker58f21322018-08-24 11:17:36 -0500420#ifdef TW_NO_MINUI_CUSTOM_FONTS
Tony Kuofd778e32015-02-05 21:25:56 +0800421#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
Ethan Yonker58f21322018-08-24 11:17:36 -0500422 gr_current_r = b;
423 gr_current_g = g;
424 gr_current_b = r;
Tony Kuofd778e32015-02-05 21:25:56 +0800425#else
Ethan Yonker58f21322018-08-24 11:17:36 -0500426 gr_current_r = r;
427 gr_current_g = g;
428 gr_current_b = b;
Tony Kuofd778e32015-02-05 21:25:56 +0800429#endif
Ethan Yonker58f21322018-08-24 11:17:36 -0500430#endif
431
432 if (gr_draw->pixel_bytes == 2) {
433 gr_current_a = a;
434 gr_convert_rgb_555(r, g, b);
435 return;
436 }
437
Luke Song846012f2017-09-13 15:56:16 -0700438 uint32_t r32 = r, g32 = g, b32 = b, a32 = a;
Doug Zongker16f97c32014-03-06 16:16:05 -0800439#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA)
Luke Song846012f2017-09-13 15:56:16 -0700440 gr_current = (a32 << 24) | (r32 << 16) | (g32 << 8) | b32;
Doug Zongker16f97c32014-03-06 16:16:05 -0800441#else
Luke Song846012f2017-09-13 15:56:16 -0700442 gr_current = (a32 << 24) | (b32 << 16) | (g32 << 8) | r32;
Doug Zongker16f97c32014-03-06 16:16:05 -0800443#endif
444}
445
Luke Song846012f2017-09-13 15:56:16 -0700446void gr_clear() {
Ethan Yonker58f21322018-08-24 11:17:36 -0500447 if (gr_draw->pixel_bytes == 2) {
448 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
449 return;
450 }
Ethan Yonkere96182e2015-10-13 19:32:03 -0500451
Ethan Yonker58f21322018-08-24 11:17:36 -0500452 // This code only works on 32bpp devices
Luke Song846012f2017-09-13 15:56:16 -0700453 if ((gr_current & 0xff) == ((gr_current >> 8) & 0xff) &&
454 (gr_current & 0xff) == ((gr_current >> 16) & 0xff) &&
455 (gr_current & 0xff) == ((gr_current >> 24) & 0xff) &&
456 gr_draw->row_bytes == gr_draw->width * gr_draw->pixel_bytes) {
457 memset(gr_draw->data, gr_current & 0xff, gr_draw->height * gr_draw->row_bytes);
458 } else {
459 uint32_t* px = reinterpret_cast<uint32_t*>(gr_draw->data);
460 int row_diff = gr_draw->row_bytes / gr_draw->pixel_bytes - gr_draw->width;
461 for (int y = 0; y < gr_draw->height; ++y) {
462 for (int x = 0; x < gr_draw->width; ++x) {
463 *px++ = gr_current;
464 }
465 px += row_diff;
Doug Zongker16f97c32014-03-06 16:16:05 -0800466 }
Luke Song846012f2017-09-13 15:56:16 -0700467 }
Doug Zongker02ec6b82012-08-22 17:26:40 -0700468}
469
Luke Song846012f2017-09-13 15:56:16 -0700470void gr_fill(int x1, int y1, int x2, int y2) {
471 x1 += overscan_offset_x;
472 y1 += overscan_offset_y;
Doug Zongkerc560a672012-12-18 16:31:27 -0800473
Luke Song846012f2017-09-13 15:56:16 -0700474 x2 += overscan_offset_x;
475 y2 += overscan_offset_y;
Doug Zongkerc560a672012-12-18 16:31:27 -0800476
Luke Song846012f2017-09-13 15:56:16 -0700477 if (outside(x1, y1) || outside(x2 - 1, y2 - 1)) return;
Doug Zongker16f97c32014-03-06 16:16:05 -0800478
Luke Song846012f2017-09-13 15:56:16 -0700479 int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
Ethan Yonker58f21322018-08-24 11:17:36 -0500480 if (gr_draw->pixel_bytes == 2) {
481 uint16_t* p = pixel_at16(gr_draw, x1, y1, row_pixels);
482 uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24));
483 if (alpha > 0) {
484 for (int y = y1; y < y2; ++y) {
485 uint16_t* px = p;
486 for (int x = x1; x < x2; ++x) {
487 *px = pixel_blend16(alpha, *px);
488 incr_x16(&px, row_pixels);
Doug Zongker16f97c32014-03-06 16:16:05 -0800489 }
Ethan Yonker58f21322018-08-24 11:17:36 -0500490 incr_y16(&p, row_pixels);
491 }
Doug Zongker16f97c32014-03-06 16:16:05 -0800492 }
Ethan Yonker58f21322018-08-24 11:17:36 -0500493 return;
494 }
495 { // open brace to maintain separation between uint16_t p and uint32_t p
Luke Song846012f2017-09-13 15:56:16 -0700496 uint32_t* p = pixel_at(gr_draw, x1, y1, row_pixels);
497 uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24));
498 if (alpha > 0) {
499 for (int y = y1; y < y2; ++y) {
500 uint32_t* px = p;
501 for (int x = x1; x < x2; ++x) {
502 *px = pixel_blend(alpha, *px);
503 incr_x(&px, row_pixels);
504 }
505 incr_y(&p, row_pixels);
Doug Zongkerc560a672012-12-18 16:31:27 -0800506 }
Luke Song846012f2017-09-13 15:56:16 -0700507 }
Ethan Yonker58f21322018-08-24 11:17:36 -0500508 } // close brace to maintain separation between uint16_t p and uint32_t p
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800509}
510
Ethan Yonkere96182e2015-10-13 19:32:03 -0500511void gr_blit_32to16(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
Ethan Yonker58f21322018-08-24 11:17:36 -0500512 if (rotation)
513 printf("gr_blit_32to16 does not support rotation!\n"); // but we'll draw something in the wrong spot anyway because, why not!
Ethan Yonkere96182e2015-10-13 19:32:03 -0500514
Ethan Yonker58f21322018-08-24 11:17:36 -0500515 dx += overscan_offset_x;
516 dy += overscan_offset_y;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500517
Ethan Yonker58f21322018-08-24 11:17:36 -0500518 if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500519
Ethan Yonker58f21322018-08-24 11:17:36 -0500520 unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes;
521 unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500522
Ethan Yonker58f21322018-08-24 11:17:36 -0500523 int i, j;
524 for (i = 0; i < h; ++i) {
525 unsigned char* spx = src_p;
526 unsigned char* dpx = dst_p;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500527
Ethan Yonker58f21322018-08-24 11:17:36 -0500528 for (j = 0; j < w; ++j) {
529 unsigned a = spx[3];
530
531 if (a == 0) {
532 spx += source->pixel_bytes;
533 dpx += gr_draw->pixel_bytes;
534 } else {
535 unsigned r5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF;
536 unsigned g5 = (((*spx++ & 0xFF) * 0x3F) + 0x7F) / 0xFF;
537 unsigned b5 = (((*spx++ & 0xFF) * 0x1F) + 0x7F) / 0xFF;
538 spx++;
539 if (a == 255) {
540 *dpx++ = (g5 << 5) + (b5);
541 *dpx++ = (r5 << 3) + (g5 >> 3);
542 } else {
543 blend_16bpp(dpx, r5, g5, b5, a);
544 spx += source->pixel_bytes;
Ethan Yonkere96182e2015-10-13 19:32:03 -0500545 }
Ethan Yonker58f21322018-08-24 11:17:36 -0500546 }
Ethan Yonkere96182e2015-10-13 19:32:03 -0500547 }
Ethan Yonker58f21322018-08-24 11:17:36 -0500548 src_p += source->row_bytes;
549 dst_p += gr_draw->row_bytes;
550 }
Ethan Yonkere96182e2015-10-13 19:32:03 -0500551}
552
Doug Zongker16f97c32014-03-06 16:16:05 -0800553void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
Luke Song846012f2017-09-13 15:56:16 -0700554 if (source == NULL) return;
Doug Zongker16f97c32014-03-06 16:16:05 -0800555
Luke Song846012f2017-09-13 15:56:16 -0700556 if (gr_draw->pixel_bytes != source->pixel_bytes) {
Ethan Yonker58f21322018-08-24 11:17:36 -0500557 if (gr_draw->pixel_bytes == 2 && source->pixel_bytes == 4) {
558 gr_blit_32to16(source, sx, sy, w, h, dx, dy);
559 return;
560 } else {
561 printf("gr_blit: source has wrong format\n");
562 return;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800563 }
Luke Song846012f2017-09-13 15:56:16 -0700564 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800565
Luke Song846012f2017-09-13 15:56:16 -0700566 dx += overscan_offset_x;
567 dy += overscan_offset_y;
Doug Zongkerc560a672012-12-18 16:31:27 -0800568
Luke Song846012f2017-09-13 15:56:16 -0700569 if (outside(dx, dy) || outside(dx + w - 1, dy + h - 1)) return;
Doug Zongker16f97c32014-03-06 16:16:05 -0800570
Luke Song846012f2017-09-13 15:56:16 -0700571 if (rotation) {
572 int src_row_pixels = source->row_bytes / source->pixel_bytes;
573 int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
574 uint32_t* src_py = reinterpret_cast<uint32_t*>(source->data) + sy * source->row_bytes / 4 + sx;
575 uint32_t* dst_py = pixel_at(gr_draw, dx, dy, row_pixels);
576
577 for (int y = 0; y < h; y += 1) {
578 uint32_t* src_px = src_py;
579 uint32_t* dst_px = dst_py;
580 for (int x = 0; x < w; x += 1) {
581 *dst_px = *src_px++;
582 incr_x(&dst_px, row_pixels);
583 }
584 src_py += src_row_pixels;
585 incr_y(&dst_py, row_pixels);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800586 }
Luke Song846012f2017-09-13 15:56:16 -0700587 } else {
588 unsigned char* src_p = source->data + sy * source->row_bytes + sx * source->pixel_bytes;
589 unsigned char* dst_p = gr_draw->data + dy * gr_draw->row_bytes + dx * gr_draw->pixel_bytes;
Doug Zongker16f97c32014-03-06 16:16:05 -0800590
591 int i;
592 for (i = 0; i < h; ++i) {
Luke Song846012f2017-09-13 15:56:16 -0700593 memcpy(dst_p, src_p, w * source->pixel_bytes);
594 src_p += source->row_bytes;
595 dst_p += gr_draw->row_bytes;
Doug Zongker16f97c32014-03-06 16:16:05 -0800596 }
Luke Song846012f2017-09-13 15:56:16 -0700597 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800598}
599
Doug Zongker16f97c32014-03-06 16:16:05 -0800600unsigned int gr_get_width(GRSurface* surface) {
Luke Song846012f2017-09-13 15:56:16 -0700601 if (surface == NULL) {
602 return 0;
603 }
604 return surface->width;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800605}
606
Doug Zongker16f97c32014-03-06 16:16:05 -0800607unsigned int gr_get_height(GRSurface* surface) {
Luke Song846012f2017-09-13 15:56:16 -0700608 if (surface == NULL) {
609 return 0;
610 }
611 return surface->height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800612}
613
Ethan Yonker39662b22017-05-23 08:34:02 -0500614#ifdef TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800615static void gr_init_font(void)
616{
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700617 gr_font = reinterpret_cast<GRFont*>(calloc(sizeof(*gr_font), 1));
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800618
Doug Zongkera418aa72014-03-17 12:10:02 -0700619 int res = res_create_alpha_surface("font", &(gr_font->texture));
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800620 if (res == 0) {
621 // The font image should be a 96x2 array of character images. The
622 // columns are the printable ASCII characters 0x20 - 0x7f. The
623 // top row is regular text; the bottom row is bold.
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500624 gr_font->char_width = gr_font->texture->width / 96;
625 gr_font->char_height = gr_font->texture->height / 2;
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800626 } else {
Doug Zongker55a36ac2013-03-04 15:49:02 -0800627 printf("failed to read font: res=%d\n", res);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800628
629 // fall back to the compiled-in font.
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700630 gr_font->texture = reinterpret_cast<GRSurface*>(malloc(sizeof(*gr_font->texture)));
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800631 gr_font->texture->width = font.width;
632 gr_font->texture->height = font.height;
Doug Zongker16f97c32014-03-06 16:16:05 -0800633 gr_font->texture->row_bytes = font.width;
634 gr_font->texture->pixel_bytes = 1;
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800635
Elliott Hughes07cfb8f2015-04-10 13:12:05 -0700636 unsigned char* bits = reinterpret_cast<unsigned char*>(malloc(font.width * font.height));
637 gr_font->texture->data = reinterpret_cast<unsigned char*>(bits);
Doug Zongker6fd59ac2013-03-06 15:01:11 -0800638
639 unsigned char data;
640 unsigned char* in = font.rundata;
641 while((data = *in++)) {
642 memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
643 bits += (data & 0x7f);
644 }
645
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500646 gr_font->char_width = font.char_width;
647 gr_font->char_height = font.char_height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800648 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800649}
650
Ethan Yonker84d61ce2017-05-10 16:11:35 -0500651void gr_set_font(__attribute__ ((unused))const char* name) {
652 //this cm function is made to change font. Don't care, just init the font:
653 gr_init_font();
654 return;
655}
Ethan Yonker39662b22017-05-23 08:34:02 -0500656#else // TW_NO_MINUI_CUSTOM_FONTS
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700657int gr_init_font(const char* name, GRFont** dest) {
Luke Song846012f2017-09-13 15:56:16 -0700658 GRFont* font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
659 if (font == nullptr) {
660 return -1;
661 }
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700662
Luke Song846012f2017-09-13 15:56:16 -0700663 int res = res_create_alpha_surface(name, &(font->texture));
664 if (res < 0) {
665 free(font);
666 return res;
667 }
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700668
Luke Song846012f2017-09-13 15:56:16 -0700669 // The font image should be a 96x2 array of character images. The
670 // columns are the printable ASCII characters 0x20 - 0x7f. The
671 // top row is regular text; the bottom row is bold.
672 font->char_width = font->texture->width / 96;
673 font->char_height = font->texture->height / 2;
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700674
Luke Song846012f2017-09-13 15:56:16 -0700675 *dest = font;
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700676
Luke Song846012f2017-09-13 15:56:16 -0700677 return 0;
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700678}
679
Luke Song846012f2017-09-13 15:56:16 -0700680static void gr_init_font(void) {
681 int res = gr_init_font("font", &gr_font);
682 if (res == 0) {
683 return;
684 }
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700685
Luke Song846012f2017-09-13 15:56:16 -0700686 printf("failed to read font: res=%d\n", res);
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700687
Luke Song846012f2017-09-13 15:56:16 -0700688 // fall back to the compiled-in font.
689 gr_font = static_cast<GRFont*>(calloc(1, sizeof(*gr_font)));
690 gr_font->texture = static_cast<GRSurface*>(malloc(sizeof(*gr_font->texture)));
691 gr_font->texture->width = font.width;
692 gr_font->texture->height = font.height;
693 gr_font->texture->row_bytes = font.width;
694 gr_font->texture->pixel_bytes = 1;
Damien Bargiacchid00f5eb2016-09-09 07:14:08 -0700695
Luke Song846012f2017-09-13 15:56:16 -0700696 unsigned char* bits = static_cast<unsigned char*>(malloc(font.width * font.height));
697 gr_font->texture->data = bits;
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700698
Luke Song846012f2017-09-13 15:56:16 -0700699 unsigned char data;
700 unsigned char* in = font.rundata;
701 while ((data = *in++)) {
702 memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f);
703 bits += (data & 0x7f);
704 }
Damien Bargiacchi35fff612016-08-11 15:57:03 -0700705
Luke Song846012f2017-09-13 15:56:16 -0700706 gr_font->char_width = font.char_width;
707 gr_font->char_height = font.char_height;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800708}
Ethan Yonker39662b22017-05-23 08:34:02 -0500709#endif // TW_NO_MINUI_CUSTOM_FONTS
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800710
Doug Zongker5290f202014-03-11 13:22:04 -0700711void gr_flip() {
Tao Bao557fa1f2017-02-07 12:51:00 -0800712 gr_draw = gr_backend->Flip();
Doug Zongker5290f202014-03-11 13:22:04 -0700713}
714
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800715int gr_init(void)
716{
Tao Bao557fa1f2017-02-07 12:51:00 -0800717 gr_init_font();
Doug Zongker16f97c32014-03-06 16:16:05 -0800718
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500719 auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendOverlay>() };
Tao Bao557fa1f2017-02-07 12:51:00 -0800720 gr_draw = backend->Init();
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800721
Ethan Yonkerb386f712017-01-20 14:30:28 -0600722#ifdef MSM_BSP
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500723 if (gr_draw) {
724 printf("Using overlay graphics.\n");
Ethan Yonkera59da092015-10-13 19:35:05 -0500725 }
Ethan Yonkerb386f712017-01-20 14:30:28 -0600726#endif
Ethan Yonkera59da092015-10-13 19:35:05 -0500727
728#ifndef MSM_BSP
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500729 if (!gr_draw) {
730 backend = std::make_unique<MinuiBackendAdf>();
731 gr_draw = backend->Init();
732 if (gr_draw)
733 printf("Using adf graphics.\n");
Greg Hackmann41909dd2014-04-25 10:39:50 -0700734 }
Ethan Yonkera59da092015-10-13 19:35:05 -0500735#else
736 printf("Skipping adf graphics because TW_TARGET_USES_QCOM_BSP := true\n");
737#endif
Greg Hackmann41909dd2014-04-25 10:39:50 -0700738
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500739 if (!gr_draw) {
740 backend = std::make_unique<MinuiBackendDrm>();
741 gr_draw = backend->Init();
Ethan Yonkera59da092015-10-13 19:35:05 -0500742 if (gr_draw)
743 printf("Using drm graphics.\n");
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700744 }
745
Ethan Yonker8373cfe2017-09-08 06:50:54 -0500746 if (!gr_draw) {
747 backend = std::make_unique<MinuiBackendFbdev>();
748 gr_draw = backend->Init();
749 if (gr_draw)
Ethan Yonkera59da092015-10-13 19:35:05 -0500750 printf("Using fbdev graphics.\n");
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800751 }
752
Tao Bao557fa1f2017-02-07 12:51:00 -0800753 if (!gr_draw) {
754 return -1;
755 }
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800756
Tao Bao557fa1f2017-02-07 12:51:00 -0800757 gr_backend = backend.release();
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800758
Tao Bao557fa1f2017-02-07 12:51:00 -0800759 overscan_offset_x = gr_draw->width * overscan_percent / 100;
760 overscan_offset_y = gr_draw->height * overscan_percent / 100;
761
762 gr_flip();
763 gr_flip();
764
Luke Song846012f2017-09-13 15:56:16 -0700765 gr_rotate(DEFAULT_ROTATION);
766
767 if (gr_draw->pixel_bytes != 4) {
768 printf("gr_init: Only 4-byte pixel formats supported\n");
769 }
770
Tao Bao557fa1f2017-02-07 12:51:00 -0800771 return 0;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800772}
773
Tao Bao557fa1f2017-02-07 12:51:00 -0800774void gr_exit() {
775 delete gr_backend;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800776}
777
Tao Bao557fa1f2017-02-07 12:51:00 -0800778int gr_fb_width() {
Luke Song846012f2017-09-13 15:56:16 -0700779 return rotation % 2 ? gr_draw->height - 2 * overscan_offset_y
780 : gr_draw->width - 2 * overscan_offset_x;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800781}
782
Tao Bao557fa1f2017-02-07 12:51:00 -0800783int gr_fb_height() {
Luke Song846012f2017-09-13 15:56:16 -0700784 return rotation % 2 ? gr_draw->width - 2 * overscan_offset_x
785 : gr_draw->height - 2 * overscan_offset_y;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800786}
Dima Zavin4daf48a2011-08-30 11:59:20 -0700787
Tao Bao557fa1f2017-02-07 12:51:00 -0800788void gr_fb_blank(bool blank) {
789 gr_backend->Blank(blank);
Dima Zavin4daf48a2011-08-30 11:59:20 -0700790}
Luke Song846012f2017-09-13 15:56:16 -0700791
792void gr_rotate(GRRotation rot) {
793 rotation = rot;
794}