summaryrefslogtreecommitdiff
path: root/framebuffer_device.cpp (plain)
blob: 045dcc6b55322fc806e6f7686aa510bbefe6c95f
1/*
2 * Copyright (C) 2010 ARM Limited. All rights reserved.
3 *
4 * Copyright (C) 2008 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <string.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <stdlib.h>
23#include <sys/ioctl.h>
24#include <linux/fb.h>
25#include "gralloc_priv.h"
26#include <hardware/hwcomposer_defs.h>
27
28#include <cutils/log.h>
29#include <cutils/atomic.h>
30#include <hardware/hardware.h>
31#include <hardware/gralloc.h>
32
33#include <GLES/gl.h>
34
35#include "alloc_device.h"
36#include "gralloc_priv.h"
37#include "gralloc_helper.h"
38#include "gralloc_vsync.h"
39
40static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval)
41{
42 if (interval < dev->minSwapInterval)
43 {
44 interval = dev->minSwapInterval;
45 }
46 else if (interval > dev->maxSwapInterval)
47 {
48 interval = dev->maxSwapInterval;
49 }
50
51 private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
52 m->swapInterval = interval;
53
54 if (0 == interval) gralloc_vsync_disable(dev);
55 else gralloc_vsync_enable(dev);
56
57 return 0;
58}
59
60static int init_frame_buffer(struct private_module_t* module,struct framebuffer_t* fb)
61{
62 if (fb->fb_hnd != NULL)
63 {
64 ALOGD("init already called before.");
65 return 0;
66 }
67 pthread_mutex_lock(&module->lock);
68 framebuffer_info_t* fbinfo = &(fb->fb_info);
69 fbinfo->displayType = HWC_DISPLAY_PRIMARY;
70 fbinfo->fbIdx = getOsdIdx(fbinfo->displayType);
71
72 int err = init_frame_buffer_locked(fbinfo);
73 int bufferSize = fbinfo->finfo.line_length * fbinfo->info.yres;
74
75 // Create a "fake" buffer object for the entire frame buffer memory, and store it in the module
76 fb->fb_hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, 0, fbinfo->fbSize, 0,
77 0, fbinfo->fd, bufferSize, 0);
78 ALOGD("init_frame_buffer get frame size %d",bufferSize);
79
80 //init fb_info
81 framebuffer_mapper_t* m = NULL;
82 private_handle_t *hnd = (private_handle_t *)fb->fb_hnd;
83 if (hnd->usage & GRALLOC_USAGE_EXTERNAL_DISP)
84 {
85 m = &(module->fb_external);
86 }
87 else
88 {
89 m = &(module->fb_primary);
90 }
91 m->fb_info = fb->fb_info;
92 //m->fb_info = &(fb->fb_info);
93
94 //Register the handle.
95 module->base.registerBuffer(&(module->base),fb->fb_hnd);
96
97 pthread_mutex_unlock(&module->lock);
98 return err;
99}
100
101static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer){
102 private_module_t* priv_t = reinterpret_cast<private_module_t*>(dev->common.module);
103 framebuffer_t* fb = reinterpret_cast<framebuffer_t*>(dev);
104 framebuffer_info_t* fbinfo = &(fb->fb_info);
105 int display_type = fbinfo->displayType;
106
107/* framebuffer_mapper_t* m = &(priv_t->fb_primary);
108#ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL
109 if (display_type == HWC_DISPLAY_EXTERNAL)
110 ALOGD("fbpost hdmi on panel");
111#else
112 if (display_type == HWC_DISPLAY_EXTERNAL)
113 m = &(priv_t->fb_external);
114#endif
115*/
116 if (private_handle_t::validate(buffer) < 0)
117 {
118 return -EINVAL;
119 }
120 if (fbinfo->currentBuffer)
121 {
122 priv_t->base.unlock(&priv_t->base, fbinfo->currentBuffer);
123 fbinfo->currentBuffer = 0;
124 }
125 private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
126 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
127 {
128 priv_t->base.lock(&priv_t->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
129 0, 0, fbinfo->info.xres, fbinfo->info.yres, NULL);
130 int rtn = fb_post_locked(fbinfo,buffer);
131 if (rtn < 0)
132 {
133 //post fail.
134 ALOGD("fb_post_locked return error %d",rtn);
135 priv_t->base.unlock(&priv_t->base, buffer);
136 return rtn;
137 }
138 } else {
139 void* fb_vaddr;
140 void* buffer_vaddr;
141 priv_t->base.lock(&priv_t->base, priv_t->fb_primary.framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY,
142 0, 0, fbinfo->info.xres, fbinfo->info.yres, &fb_vaddr);
143 priv_t->base.lock(&priv_t->base, buffer, GRALLOC_USAGE_SW_READ_RARELY,
144 0, 0, fbinfo->info.xres, fbinfo->info.yres, &buffer_vaddr);
145 memcpy(fb_vaddr, buffer_vaddr, fbinfo->finfo.line_length * fbinfo->info.yres);
146 priv_t->base.unlock(&priv_t->base, buffer);
147 priv_t->base.unlock(&priv_t->base, priv_t->fb_primary.framebuffer);
148 }
149 return 0;
150}
151
152static int fb_close(struct hw_device_t *device)
153{
154 framebuffer_t* dev = reinterpret_cast<framebuffer_t*>(device);
155 if (dev)
156 {
157#if GRALLOC_ARM_UMP_MODULE
158 ump_close();
159#endif
160 if (dev->fb_hnd)
161 {
162 #if 0
163 hw_module_t * pmodule = NULL;
164 private_module_t *m = NULL;
165 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0)
166 {
167 m = reinterpret_cast<private_module_t *>(pmodule);
168 m->base.unregisterBuffer(&(m->base),dev->fb_hnd);
169 }
170 close(dev->fb_info.fd);
171 dev->fb_info.fd= -1;
172 #endif
173
174 delete dev->fb_hnd;
175 dev->fb_hnd = 0;
176 }
177
178#if PLATFORM_SDK_VERSION > 22
179 free(dev);
180 dev = NULL;
181#else
182 delete dev;
183#endif
184 }
185 return 0;
186}
187
188int compositionComplete(struct framebuffer_device_t* dev)
189{
190 /* By doing a finish here we force the GL driver to start rendering
191 all the drawcalls up to this point, and to wait for the rendering to be complete.*/
192 glFinish();
193 /* The rendering of the backbuffer is now completed.
194 When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done
195 synchronously in the same thread, and not asynchronoulsy in a background thread later.
196 The SurfaceFlinger requires this behaviour since it releases the lock on all the
197 SourceBuffers (Layers) after the compositionComplete() function returns.
198 However this "bad" behaviour by SurfaceFlinger should not affect performance,
199 since the Applications that render the SourceBuffers (Layers) still get the
200 full renderpipeline using asynchronous rendering. So they perform at maximum speed,
201 and because of their complexity compared to the Surface flinger jobs, the Surface flinger
202 is normally faster even if it does everyhing synchronous and serial.
203 */
204 return 0;
205}
206
207int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
208{
209 int status = -EINVAL;
210
211#if 0
212 alloc_device_t* gralloc_device;
213#if DISABLE_FRAMEBUFFER_HAL == 1
214 AERR("Framebuffer HAL not support/disabled %s",
215#ifdef MALI_DISPLAY_VERSION
216 "with MALI display enable");
217#else
218 "");
219#endif
220 return -ENODEV;
221#endif
222 status = gralloc_open(module, &gralloc_device);
223 if (status < 0)
224 {
225 return status;
226 }
227#endif
228#if DISABLE_FRAMEBUFFER_HAL == 1
229 AERR("Framebuffer HAL not support/disabled %s",
230#ifdef MALI_DISPLAY_VERSION
231 "with MALI display enable");
232#else
233 "");
234#endif
235 return -ENODEV;
236#endif
237
238#if PLATFORM_SDK_VERSION > 22
239 /* malloc is used instead of 'new' to instantiate the struct framebuffer_device_t
240 * C++11 spec specifies that if a class/struct has a const member,default constructor
241 * is deleted. So, if 'new' is used to instantiate the class/struct, it will throw
242 * error complaining about deleted constructor. Even if the struct is wrapped in a class
243 * it will still try to use the base class constructor to initialize the members, resulting
244 * in error 'deleted constructor'.
245 * This leaves two options
246 * Option 1: initialize the const members at the instantiation time. With {value1, value2 ..}
247 * Which relies on the order of the members, and if members are reordered or a new member is introduced
248 * it will end up assiging wrong value to members. Designated assignment as well has been removed in C++11
249 * Option 2: use malloc instead of 'new' to allocate the class/struct and initialize the members in code.
250 * This is the only maintainable option available.
251 */
252
253 framebuffer_t *fb = (framebuffer_t *)malloc(sizeof(framebuffer_t));//new framebuffer_t();
254#else
255 /*Init the framebuffer data*/
256 framebuffer_t *fb = new framebuffer_t();
257#endif
258
259 memset(fb, 0, sizeof(*fb));
260
261 framebuffer_device_t *dev = &(fb->base);
262 framebuffer_info_t *fbinfo = &(fb->fb_info);
263
264 /*get gralloc module to register framebuffer*/
265 private_module_t* priv_t = (private_module_t*)module;
266 framebuffer_mapper_t* m =&(priv_t->fb_primary);
267 status = init_frame_buffer(priv_t,fb);
268 if (status < 0)
269 {
270 #if 0
271 gralloc_close(gralloc_device);
272 #endif
273#if PLATFORM_SDK_VERSION > 22
274 free(fb);
275 fb = NULL;
276#else
277 delete fb;
278#endif
279 return status;
280 }
281
282 /* initialize the procs */
283 dev->common.tag = HARDWARE_DEVICE_TAG;
284 dev->common.version = 0;
285 dev->common.module = const_cast<hw_module_t*>(module);
286 dev->common.close = fb_close;
287 dev->setSwapInterval = fb_set_swap_interval;
288 dev->post = fb_post;
289 dev->setUpdateRect = 0;
290 dev->compositionComplete = &compositionComplete;
291
292 int stride = fbinfo->finfo.line_length / (fbinfo->info.bits_per_pixel >> 3);
293 const_cast<uint32_t&>(dev->flags) = 0;
294 const_cast<uint32_t&>(dev->width) = fbinfo->info.xres;
295 const_cast<uint32_t&>(dev->height) = fbinfo->info.yres;
296 const_cast<int&>(dev->stride) = stride;
297 const_cast<int&>(dev->format) = (bits_per_pixel() == 16) ? HAL_PIXEL_FORMAT_RGB_565 : HAL_PIXEL_FORMAT_RGBA_8888;
298 const_cast<float&>(dev->xdpi) = fbinfo->xdpi;
299 const_cast<float&>(dev->ydpi) = fbinfo->ydpi;
300 const_cast<float&>(dev->fps) = fbinfo->fps;
301 const_cast<int&>(dev->minSwapInterval) = 0;
302 const_cast<int&>(dev->maxSwapInterval) = 1;
303 *device = &dev->common;
304
305 gralloc_vsync_enable(dev);
306
307 return status;
308}
309