blob: 67c836ed5f319953f454087edc175f7bac0381f7 [file] [log] [blame]
Vojtech Bocek03fd6c52014-03-13 18:46:34 +01001/*
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
17#include <stdio.h>
Matt Mower2b18a532015-02-20 16:58:05 -060018#include <stdlib.h>
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010019#include <png.h>
20#include <pixelflinger/pixelflinger.h>
21#include <linux/fb.h>
22
23#include "minui.h"
24
25struct fb_var_screeninfo vi;
Ethan Yonkerfbb43532015-12-28 21:54:50 +010026extern GGLSurface gr_mem_surface;
27extern GRSurface* gr_draw;
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010028
29int gr_save_screenshot(const char *dest)
30{
31 uint32_t y, stride_bytes;
xiaolu26ffa862015-05-23 12:11:09 +080032 volatile int res = -1;
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010033 GGLContext *gl = NULL;
34 GGLSurface surface;
35 uint8_t * volatile img_data = NULL;
36 uint8_t *ptr;
xiaolu26ffa862015-05-23 12:11:09 +080037 FILE * volatile fp = NULL;
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010038 png_structp png_ptr = NULL;
39 png_infop info_ptr = NULL;
40
41 fp = fopen(dest, "wb");
42 if(!fp)
43 goto exit;
44
Ethan Yonkerfbb43532015-12-28 21:54:50 +010045 img_data = (uint8_t *)malloc(gr_mem_surface.stride * gr_mem_surface.height * gr_draw->pixel_bytes);
46 if (!img_data) {
47 printf("gr_save_screenshot failed to malloc img_data\n");
48 goto exit;
49 }
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010050 surface.version = sizeof(surface);
51 surface.width = gr_mem_surface.width;
52 surface.height = gr_mem_surface.height;
xiaolu26ffa862015-05-23 12:11:09 +080053 surface.stride = gr_mem_surface.stride;
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010054 surface.data = img_data;
notsyncing8e4e8ec2018-06-09 10:40:50 +080055
56#if defined(RECOVERY_BGRA)
57 surface.format = GGL_PIXEL_FORMAT_BGRA_8888;
58#else
xiaolu26ffa862015-05-23 12:11:09 +080059 surface.format = GGL_PIXEL_FORMAT_RGBA_8888;
notsyncing8e4e8ec2018-06-09 10:40:50 +080060#endif
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010061
62 gglInit(&gl);
63 gl->colorBuffer(gl, &surface);
64 gl->activeTexture(gl, 0);
65
xiaolu26ffa862015-05-23 12:11:09 +080066 if(gr_mem_surface.format == GGL_PIXEL_FORMAT_RGBX_8888)
67 gl->disable(gl, GGL_BLEND);
68
Vojtech Bocek03fd6c52014-03-13 18:46:34 +010069 gl->bindTexture(gl, &gr_mem_surface);
70 gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
71 gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
72 gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
73 gl->enable(gl, GGL_TEXTURE_2D);
74 gl->texCoord2i(gl, 0, 0);
75 gl->recti(gl, 0, 0, gr_mem_surface.width, gr_mem_surface.height);
76
77 gglUninit(gl);
78 gl = NULL;
79
80 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
81 if (!png_ptr)
82 goto exit;
83
84 info_ptr = png_create_info_struct(png_ptr);
85 if (info_ptr == NULL)
86 goto exit;
87
88 if (setjmp(png_jmpbuf(png_ptr)))
89 goto exit;
90
91 png_init_io(png_ptr, fp);
92 png_set_IHDR(png_ptr, info_ptr, surface.width, surface.height,
93 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
94 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
95 png_write_info(png_ptr, info_ptr);
96
xiaolu26ffa862015-05-23 12:11:09 +080097 // To remove the alpha channel for PNG_COLOR_TYPE_RGB format,
98 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
99
Vojtech Bocek03fd6c52014-03-13 18:46:34 +0100100 ptr = img_data;
xiaolu26ffa862015-05-23 12:11:09 +0800101 stride_bytes = surface.stride*4;
Vojtech Bocek03fd6c52014-03-13 18:46:34 +0100102 for(y = 0; y < surface.height; ++y)
103 {
104 png_write_row(png_ptr, ptr);
105 ptr += stride_bytes;
106 }
107
108 png_write_end(png_ptr, NULL);
109
110 res = 0;
111exit:
112 if(info_ptr)
113 png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
114 if(png_ptr)
115 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
116 if(gl)
117 gglUninit(gl);
118 if(img_data)
119 free(img_data);
120 if(fp)
121 fclose(fp);
122 return res;
123}