blob: a53faa865e903e11b93a8030460f203a5138b8f4 [file] [log] [blame]
Ethan Yonkerfbb43532015-12-28 21:54:50 +01001/*
2 * Copyright (C) 2014 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
17#include <stdbool.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <errno.h>
22
23#include <fcntl.h>
24#include <stdio.h>
25
26#include <sys/cdefs.h>
27#include <sys/ioctl.h>
28#include <sys/mman.h>
29#include <sys/types.h>
30
31#include <linux/fb.h>
32#include <linux/kd.h>
33
34#ifdef MSM_BSP
35#include <linux/msm_mdp.h>
36#include <linux/msm_ion.h>
37#endif
38
39#include "minui.h"
40#include "graphics.h"
41#include <pixelflinger/pixelflinger.h>
42
43#define MDP_V4_0 400
44#define MAX_DISPLAY_DIM 2048
45
46static GRSurface* overlay_init(minui_backend*);
47static GRSurface* overlay_flip(minui_backend*);
48static void overlay_blank(minui_backend*, bool);
49static void overlay_exit(minui_backend*);
50
51static GRSurface gr_framebuffer;
52static GRSurface* gr_draw = NULL;
Ethan Yonkerfbb43532015-12-28 21:54:50 +010053
54static fb_var_screeninfo vi;
55static int fb_fd = -1;
56static bool isMDP5 = false;
57static int leftSplit = 0;
58static int rightSplit = 0;
59#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
60
61static size_t frame_size = 0;
62
63#ifdef MSM_BSP
64typedef struct {
65 unsigned char *mem_buf;
66 int size;
67 int ion_fd;
68 int mem_fd;
69 struct ion_handle_data handle_data;
70} memInfo;
71
72//Left and right overlay id
73static int overlayL_id = MSMFB_NEW_REQUEST;
74static int overlayR_id = MSMFB_NEW_REQUEST;
75
76static memInfo mem_info;
77
78static int map_mdp_pixel_format()
79{
80 if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGB_565)
81 return MDP_RGB_565;
82 else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_BGRA_8888)
83 return MDP_BGRA_8888;
84 else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBA_8888)
85 return MDP_RGBA_8888;
86 else if (gr_framebuffer.format == GGL_PIXEL_FORMAT_RGBX_8888)
87 return MDP_RGBA_8888;
88 printf("No known pixel format for map_mdp_pixel_format, defaulting to MDP_RGB_565.\n");
89 return MDP_RGB_565;
90}
91#endif // MSM_BSP
92
93static minui_backend my_backend = {
94 .init = overlay_init,
95 .flip = overlay_flip,
96 .blank = overlay_blank,
97 .exit = overlay_exit,
98};
99
100bool target_has_overlay(char *version)
101{
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100102 int mdp_version;
103 bool overlay_supported = false;
104
105 if (strlen(version) >= 8) {
106 if(!strncmp(version, "msmfb", strlen("msmfb"))) {
107 char str_ver[4];
108 memcpy(str_ver, version + strlen("msmfb"), 3);
109 str_ver[3] = '\0';
110 mdp_version = atoi(str_ver);
111 if (mdp_version >= MDP_V4_0) {
112 overlay_supported = true;
113 }
114 } else if (!strncmp(version, "mdssfb", strlen("mdssfb"))) {
115 overlay_supported = true;
116 isMDP5 = true;
117 }
118 }
119
120 return overlay_supported;
121}
122
123minui_backend* open_overlay() {
124 fb_fix_screeninfo fi;
125 int fd;
126
127 fd = open("/dev/graphics/fb0", O_RDWR);
128 if (fd < 0) {
129 perror("open_overlay cannot open fb0");
130 return NULL;
131 }
132
133 if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
134 perror("failed to get fb0 info");
135 close(fd);
136 return NULL;
137 }
138
139 if (target_has_overlay(fi.id)) {
140#ifdef MSM_BSP
141 close(fd);
142 return &my_backend;
143#else
144 printf("Overlay graphics may work (%s), but not enabled. Use TW_TARGET_USES_QCOM_BSP := true to enable.\n", fi.id);
145#endif
146 }
147 close(fd);
148 return NULL;
149}
150
151static void overlay_blank(minui_backend* backend __unused, bool blank)
152{
153#if defined(TW_NO_SCREEN_BLANK) && defined(TW_BRIGHTNESS_PATH) && defined(TW_MAX_BRIGHTNESS)
154 int fd;
155 char brightness[4];
156 snprintf(brightness, 4, "%03d", TW_MAX_BRIGHTNESS/2);
157
158 fd = open(TW_BRIGHTNESS_PATH, O_RDWR);
159 if (fd < 0) {
160 perror("cannot open LCD backlight");
161 return;
162 }
163 write(fd, blank ? "000" : brightness, 3);
164 close(fd);
AdrianDC2948b6f2016-02-07 03:44:44 +0100165
166#ifdef TW_SECONDARY_BRIGHTNESS_PATH
167 fd = open(TW_SECONDARY_BRIGHTNESS_PATH, O_RDWR);
168 if (fd < 0) {
169 perror("cannot open LCD backlight 2");
170 return;
171 }
172 write(fd, blank ? "000" : brightness, 3);
173 close(fd);
174#endif
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100175#else
176 int ret;
177
178 ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
179 if (ret < 0)
180 perror("ioctl(): blank");
181#endif
182}
183
184#ifdef MSM_BSP
185void setDisplaySplit(void) {
186 char split[64] = {0};
187 if (!isMDP5)
188 return;
189 FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
190 if (fp) {
191 //Format "left right" space as delimiter
192 if(fread(split, sizeof(char), 64, fp)) {
193 leftSplit = atoi(split);
194 printf("Left Split=%d\n",leftSplit);
195 char *rght = strpbrk(split, " ");
196 if (rght)
197 rightSplit = atoi(rght + 1);
198 printf("Right Split=%d\n", rightSplit);
199 }
200 } else {
201 printf("Failed to open mdss_fb_split node\n");
202 }
203 if (fp)
204 fclose(fp);
205}
206
207int getLeftSplit(void) {
208 //Default even split for all displays with high res
209 int lSplit = vi.xres / 2;
210
211 //Override if split published by driver
212 if (leftSplit)
213 lSplit = leftSplit;
214
215 return lSplit;
216}
217
218int getRightSplit(void) {
219 return rightSplit;
220}
221
222int free_ion_mem(void) {
223 int ret = 0;
224
225 if (mem_info.mem_buf)
226 munmap(mem_info.mem_buf, mem_info.size);
227
228 if (mem_info.ion_fd >= 0) {
229 ret = ioctl(mem_info.ion_fd, ION_IOC_FREE, &mem_info.handle_data);
230 if (ret < 0)
231 perror("free_mem failed ");
232 }
233
234 if (mem_info.mem_fd >= 0)
235 close(mem_info.mem_fd);
236 if (mem_info.ion_fd >= 0)
237 close(mem_info.ion_fd);
238
239 memset(&mem_info, 0, sizeof(mem_info));
240 mem_info.mem_fd = -1;
241 mem_info.ion_fd = -1;
242 return 0;
243}
244
245int alloc_ion_mem(unsigned int size)
246{
247 int result;
248 struct ion_fd_data fd_data;
249 struct ion_allocation_data ionAllocData;
250
251 mem_info.ion_fd = open("/dev/ion", O_RDWR|O_DSYNC);
252 if (mem_info.ion_fd < 0) {
253 perror("ERROR: Can't open ion ");
254 return -errno;
255 }
256
257 ionAllocData.flags = 0;
258 ionAllocData.len = size;
259 ionAllocData.align = sysconf(_SC_PAGESIZE);
260#ifdef NEW_ION_HEAP
261 ionAllocData.heap_id_mask =
262#else
263 ionAllocData.heap_mask =
264#endif
265 ION_HEAP(ION_IOMMU_HEAP_ID) |
266 ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID);
267
268 result = ioctl(mem_info.ion_fd, ION_IOC_ALLOC, &ionAllocData);
269 if(result){
270 perror("ION_IOC_ALLOC Failed ");
271 close(mem_info.ion_fd);
272 return result;
273 }
274
275 fd_data.handle = ionAllocData.handle;
276 mem_info.handle_data.handle = ionAllocData.handle;
277 result = ioctl(mem_info.ion_fd, ION_IOC_MAP, &fd_data);
278 if (result) {
279 perror("ION_IOC_MAP Failed ");
280 free_ion_mem();
281 return result;
282 }
283 mem_info.mem_buf = (unsigned char *)mmap(NULL, size, PROT_READ |
284 PROT_WRITE, MAP_SHARED, fd_data.fd, 0);
285 mem_info.mem_fd = fd_data.fd;
286
287 if (!mem_info.mem_buf) {
288 perror("ERROR: mem_buf MAP_FAILED ");
289 free_ion_mem();
290 return -ENOMEM;
291 }
292
293 return 0;
294}
295
296bool isDisplaySplit(void) {
297 if (vi.xres > MAX_DISPLAY_DIM)
298 return true;
299 //check if right split is set by driver
300 if (getRightSplit())
301 return true;
302
303 return false;
304}
305
306int allocate_overlay(int fd, GRSurface gr_fb)
307{
308 int ret = 0;
309
310 if (!isDisplaySplit()) {
311 // Check if overlay is already allocated
312 if (MSMFB_NEW_REQUEST == overlayL_id) {
313 struct mdp_overlay overlayL;
314
315 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
316
317 /* Fill Overlay Data */
318 overlayL.src.width = ALIGN(gr_fb.width, 32);
319 overlayL.src.height = gr_fb.height;
320 overlayL.src.format = map_mdp_pixel_format();
321 overlayL.src_rect.w = gr_fb.width;
322 overlayL.src_rect.h = gr_fb.height;
323 overlayL.dst_rect.w = gr_fb.width;
324 overlayL.dst_rect.h = gr_fb.height;
325 overlayL.alpha = 0xFF;
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300326 // If this worked, life would have been so much easier
Aaron Kling4eccd9a2019-06-30 12:20:09 -0500327 //switch (gr_rotation) {
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300328 //case 0: overlayL.flags = MDP_ROT_NOP; break;
329 //case 90: overlayL.flags = MDP_ROT_90; break;
330 //case 180: overlayL.flags = MDP_ROT_180; break;
331 //case 270: overlayL.flags = MDP_ROT_270; break;
332 //}
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100333 overlayL.transp_mask = MDP_TRANSP_NOP;
334 overlayL.id = MSMFB_NEW_REQUEST;
335 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
336 if (ret < 0) {
337 perror("Overlay Set Failed");
338 return ret;
339 }
340 overlayL_id = overlayL.id;
341 }
342 } else {
343 float xres = vi.xres;
344 int lSplit = getLeftSplit();
345 float lSplitRatio = lSplit / xres;
346 float lCropWidth = gr_fb.width * lSplitRatio;
347 int lWidth = lSplit;
348 int rWidth = gr_fb.width - lSplit;
349 int height = gr_fb.height;
350
351 if (MSMFB_NEW_REQUEST == overlayL_id) {
352
353 struct mdp_overlay overlayL;
354
355 memset(&overlayL, 0 , sizeof (struct mdp_overlay));
356
357 /* Fill OverlayL Data */
358 overlayL.src.width = ALIGN(gr_fb.width, 32);
359 overlayL.src.height = gr_fb.height;
360 overlayL.src.format = map_mdp_pixel_format();
361 overlayL.src_rect.x = 0;
362 overlayL.src_rect.y = 0;
363 overlayL.src_rect.w = lCropWidth;
364 overlayL.src_rect.h = gr_fb.height;
365 overlayL.dst_rect.x = 0;
366 overlayL.dst_rect.y = 0;
367 overlayL.dst_rect.w = lWidth;
368 overlayL.dst_rect.h = height;
369 overlayL.alpha = 0xFF;
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300370 // If this worked, life would have been so much easier
Aaron Kling4eccd9a2019-06-30 12:20:09 -0500371 //switch (gr_rotation) {
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300372 //case 0: overlayL.flags = MDP_ROT_NOP; break;
373 //case 90: overlayL.flags = MDP_ROT_90; break;
374 //case 180: overlayL.flags = MDP_ROT_180; break;
375 //case 270: overlayL.flags = MDP_ROT_270; break;
376 //}
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100377 overlayL.transp_mask = MDP_TRANSP_NOP;
378 overlayL.id = MSMFB_NEW_REQUEST;
379 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayL);
380 if (ret < 0) {
381 perror("OverlayL Set Failed");
382 return ret;
383 }
384 overlayL_id = overlayL.id;
385 }
386 if (MSMFB_NEW_REQUEST == overlayR_id) {
387 struct mdp_overlay overlayR;
388
389 memset(&overlayR, 0 , sizeof (struct mdp_overlay));
390
391 /* Fill OverlayR Data */
392 overlayR.src.width = ALIGN(gr_fb.width, 32);
393 overlayR.src.height = gr_fb.height;
394 overlayR.src.format = map_mdp_pixel_format();
395 overlayR.src_rect.x = lCropWidth;
396 overlayR.src_rect.y = 0;
397 overlayR.src_rect.w = gr_fb.width - lCropWidth;
398 overlayR.src_rect.h = gr_fb.height;
399 overlayR.dst_rect.x = 0;
400 overlayR.dst_rect.y = 0;
401 overlayR.dst_rect.w = rWidth;
402 overlayR.dst_rect.h = height;
403 overlayR.alpha = 0xFF;
404 overlayR.flags = MDSS_MDP_RIGHT_MIXER;
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300405 // If this worked, life would have been so much easier
Aaron Kling4eccd9a2019-06-30 12:20:09 -0500406 //switch (gr_rotation) {
Vladimir Olteand32b7eb2018-07-03 00:04:03 +0300407 //case 0: overlayR.flags |= MDP_ROT_NOP; break;
408 //case 90: overlayR.flags |= MDP_ROT_90; break;
409 //case 180: overlayR.flags |= MDP_ROT_180; break;
410 //case 270: overlayR.flags |= MDP_ROT_270; break;
411 //}
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100412 overlayR.transp_mask = MDP_TRANSP_NOP;
413 overlayR.id = MSMFB_NEW_REQUEST;
414 ret = ioctl(fd, MSMFB_OVERLAY_SET, &overlayR);
415 if (ret < 0) {
416 perror("OverlayR Set Failed");
417 return ret;
418 }
419 overlayR_id = overlayR.id;
420 }
421
422 }
423 return 0;
424}
425
426int overlay_display_frame(int fd, void* data, size_t size)
427{
428 int ret = 0;
429 struct msmfb_overlay_data ovdataL, ovdataR;
430 struct mdp_display_commit ext_commit;
431
432 if (!isDisplaySplit()) {
433 if (overlayL_id == MSMFB_NEW_REQUEST) {
434 perror("display_frame failed, no overlay\n");
435 return -EINVAL;
436 }
437
438 memcpy(mem_info.mem_buf, data, size);
439
440 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
441
442 ovdataL.id = overlayL_id;
443 ovdataL.data.flags = 0;
444 ovdataL.data.offset = 0;
445 ovdataL.data.memory_id = mem_info.mem_fd;
446 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
447 if (ret < 0) {
448 perror("overlay_display_frame failed, overlay play Failed\n");
449 printf("%i, %i, %i, %i\n", ret, fb_fd, fd, errno);
450 return ret;
451 }
452 } else {
453
454 if (overlayL_id == MSMFB_NEW_REQUEST) {
455 perror("display_frame failed, no overlayL \n");
456 return -EINVAL;
457 }
458
459 memcpy(mem_info.mem_buf, data, size);
460
461 memset(&ovdataL, 0, sizeof(struct msmfb_overlay_data));
462
463 ovdataL.id = overlayL_id;
464 ovdataL.data.flags = 0;
465 ovdataL.data.offset = 0;
466 ovdataL.data.memory_id = mem_info.mem_fd;
467 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataL);
468 if (ret < 0) {
469 perror("overlay_display_frame failed, overlayL play Failed\n");
470 return ret;
471 }
472
473 if (overlayR_id == MSMFB_NEW_REQUEST) {
474 perror("display_frame failed, no overlayR \n");
475 return -EINVAL;
476 }
477 memset(&ovdataR, 0, sizeof(struct msmfb_overlay_data));
478
479 ovdataR.id = overlayR_id;
480 ovdataR.data.flags = 0;
481 ovdataR.data.offset = 0;
482 ovdataR.data.memory_id = mem_info.mem_fd;
483 ret = ioctl(fd, MSMFB_OVERLAY_PLAY, &ovdataR);
484 if (ret < 0) {
485 perror("overlay_display_frame failed, overlayR play Failed\n");
486 return ret;
487 }
488 }
489 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
490 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
491 ext_commit.wait_for_finish = 1;
492 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
493 if (ret < 0) {
494 perror("overlay_display_frame failed, overlay commit Failed\n!");
495 }
496
497 return ret;
498}
499
500static GRSurface* overlay_flip(minui_backend* backend __unused) {
501#if defined(RECOVERY_BGRA)
502 // In case of BGRA, do some byte swapping
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100503 unsigned char* ucfb_vaddr = (unsigned char*)gr_draw->data;
Simon Shifcfc6342019-01-16 13:27:01 +0800504 for (int idx = 0 ; idx < (gr_draw->height * gr_draw->row_bytes);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100505 idx += 4) {
Simon Shifcfc6342019-01-16 13:27:01 +0800506 unsigned char tmp = ucfb_vaddr[idx];
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100507 ucfb_vaddr[idx ] = ucfb_vaddr[idx + 2];
508 ucfb_vaddr[idx + 2] = tmp;
509 }
510#endif
511 // Copy from the in-memory surface to the framebuffer.
512 overlay_display_frame(fb_fd, gr_draw->data, frame_size);
513 return gr_draw;
514}
515
516int free_overlay(int fd)
517{
518 int ret = 0;
519 struct mdp_display_commit ext_commit;
520
521 if (!isDisplaySplit()) {
522 if (overlayL_id != MSMFB_NEW_REQUEST) {
523 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
524 if (ret) {
525 perror("Overlay Unset Failed");
526 overlayL_id = MSMFB_NEW_REQUEST;
527 return ret;
528 }
529 }
530 } else {
531
532 if (overlayL_id != MSMFB_NEW_REQUEST) {
533 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayL_id);
534 if (ret) {
535 perror("OverlayL Unset Failed");
536 }
537 }
538
539 if (overlayR_id != MSMFB_NEW_REQUEST) {
540 ret = ioctl(fd, MSMFB_OVERLAY_UNSET, &overlayR_id);
541 if (ret) {
542 perror("OverlayR Unset Failed");
543 overlayR_id = MSMFB_NEW_REQUEST;
544 return ret;
545 }
546 }
547 }
548 memset(&ext_commit, 0, sizeof(struct mdp_display_commit));
549 ext_commit.flags = MDP_DISPLAY_COMMIT_OVERLAY;
550 ext_commit.wait_for_finish = 1;
551 ret = ioctl(fd, MSMFB_DISPLAY_COMMIT, &ext_commit);
552 if (ret < 0) {
553 perror("ERROR: Clear MSMFB_DISPLAY_COMMIT failed!");
554 overlayL_id = MSMFB_NEW_REQUEST;
555 overlayR_id = MSMFB_NEW_REQUEST;
556 return ret;
557 }
558 overlayL_id = MSMFB_NEW_REQUEST;
559 overlayR_id = MSMFB_NEW_REQUEST;
560
561 return 0;
562}
563
564static GRSurface* overlay_init(minui_backend* backend) {
565 int fd = open("/dev/graphics/fb0", O_RDWR);
566 if (fd == -1) {
567 perror("cannot open fb0");
568 return NULL;
569 }
570
571 fb_fix_screeninfo fi;
572 if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) {
573 perror("failed to get fb0 info");
574 close(fd);
575 return NULL;
576 }
577
578 if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) {
579 perror("failed to get fb0 info");
580 close(fd);
581 return NULL;
582 }
583
584 // We print this out for informational purposes only, but
585 // throughout we assume that the framebuffer device uses an RGBX
586 // pixel format. This is the case for every development device I
587 // have access to. For some of those devices (eg, hammerhead aka
588 // Nexus 5), FBIOGET_VSCREENINFO *reports* that it wants a
589 // different format (XBGR) but actually produces the correct
590 // results on the display when you write RGBX.
591 //
592 // If you have a device that actually *needs* another pixel format
593 // (ie, BGRX, or 565), patches welcome...
594
595 printf("fb0 reports (possibly inaccurate):\n"
596 " vi.bits_per_pixel = %d\n"
597 " vi.red.offset = %3d .length = %3d\n"
598 " vi.green.offset = %3d .length = %3d\n"
599 " vi.blue.offset = %3d .length = %3d\n",
600 vi.bits_per_pixel,
601 vi.red.offset, vi.red.length,
602 vi.green.offset, vi.green.length,
603 vi.blue.offset, vi.blue.length);
604
605 gr_framebuffer.width = vi.xres;
606 gr_framebuffer.height = vi.yres;
607 gr_framebuffer.row_bytes = fi.line_length;
608 gr_framebuffer.pixel_bytes = vi.bits_per_pixel / 8;
609 //gr_framebuffer.data = reinterpret_cast<uint8_t*>(bits);
610 if (vi.bits_per_pixel == 16) {
611 printf("setting GGL_PIXEL_FORMAT_RGB_565\n");
612 gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565;
Ziyan4fea38a2016-01-28 01:19:35 +0100613 } else if (vi.red.offset == 8 || vi.red.offset == 16) {
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100614 printf("setting GGL_PIXEL_FORMAT_BGRA_8888\n");
615 gr_framebuffer.format = GGL_PIXEL_FORMAT_BGRA_8888;
616 } else if (vi.red.offset == 0) {
617 printf("setting GGL_PIXEL_FORMAT_RGBA_8888\n");
618 gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBA_8888;
619 } else if (vi.red.offset == 24) {
620 printf("setting GGL_PIXEL_FORMAT_RGBX_8888\n");
621 gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888;
622 } else {
623 if (vi.red.length == 8) {
624 printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGBX_8888\n");
625 gr_framebuffer.format = GGL_PIXEL_FORMAT_RGBX_8888;
626 } else {
627 printf("No valid pixel format detected, trying GGL_PIXEL_FORMAT_RGB_565\n");
628 gr_framebuffer.format = GGL_PIXEL_FORMAT_RGB_565;
629 }
630 }
631
632 frame_size = fi.line_length * vi.yres;
633
634 gr_framebuffer.data = reinterpret_cast<uint8_t*>(calloc(frame_size, 1));
635 if (gr_framebuffer.data == NULL) {
636 perror("failed to calloc framebuffer");
637 close(fd);
638 return NULL;
639 }
640
641 gr_draw = &gr_framebuffer;
642 fb_fd = fd;
643
644 printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height);
645
646 overlay_blank(backend, true);
647 overlay_blank(backend, false);
648
649 if (!alloc_ion_mem(frame_size))
650 allocate_overlay(fb_fd, gr_framebuffer);
651
652 return gr_draw;
653}
654
655static void overlay_exit(minui_backend* backend __unused) {
656 free_overlay(fb_fd);
657 free_ion_mem();
658
659 close(fb_fd);
660 fb_fd = -1;
661
662 if (gr_draw) {
663 free(gr_draw->data);
664 free(gr_draw);
665 }
666 gr_draw = NULL;
667}
668#else // MSM_BSP
669static GRSurface* overlay_flip(minui_backend* backend __unused) {
670 return NULL;
671}
672
673static GRSurface* overlay_init(minui_backend* backend __unused) {
674 return NULL;
675}
676
677static void overlay_exit(minui_backend* backend __unused) {
678 return;
679}
680#endif // MSM_BSP