blob: 02d2b102b4a0e86933426e77ad47bd572ac4a1d3 [file] [log] [blame]
Mathias Agopian3e876012012-06-07 17:52:54 -07001/*
2 **
3 ** Copyright 2007 The Android Open Source Project
4 **
5 ** Licensed under the Apache License Version 2.0(the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing software
12 ** distributed under the License is distributed on an "AS IS" BASIS
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21#include <errno.h>
22
23#include <cutils/log.h>
24
25#include <utils/String8.h>
26
27#include <ui/Rect.h>
28
29#include <EGL/egl.h>
30
31#include <hardware/hardware.h>
32#include <gui/SurfaceTextureClient.h>
33#include <ui/GraphicBuffer.h>
34
35#include "DisplayHardware/FramebufferSurface.h"
36
37// ----------------------------------------------------------------------------
38namespace android {
39// ----------------------------------------------------------------------------
40
41
42/*
43 * This implements the (main) framebuffer management. This class is used
44 * mostly by SurfaceFlinger, but also by command line GL application.
45 *
46 */
47
48FramebufferSurface::FramebufferSurface()
49 : SurfaceTextureClient(),
50 fbDev(0), mCurrentBufferIndex(-1), mUpdateOnDemand(false)
51{
52 hw_module_t const* module;
53 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
54 int stride;
55 int err;
56 int i;
57 err = framebuffer_open(module, &fbDev);
58 ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
59
60 // bail out if we can't initialize the modules
61 if (!fbDev)
62 return;
63
64 mUpdateOnDemand = (fbDev->setUpdateRect != 0);
65
66 const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
67 const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
68 const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
69 const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval;
70 const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;
71 } else {
72 ALOGE("Couldn't get gralloc module");
73 }
74
75 class GraphicBufferAlloc : public BnGraphicBufferAlloc {
76 public:
77 GraphicBufferAlloc() { };
78 virtual ~GraphicBufferAlloc() { };
79 virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
80 PixelFormat format, uint32_t usage, status_t* error) {
81 sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
82 return graphicBuffer;
83 }
84 };
85
86 mBufferQueue = new BufferQueue(true, NUM_FRAME_BUFFERS, new GraphicBufferAlloc());
87 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB|GRALLOC_USAGE_HW_RENDER|GRALLOC_USAGE_HW_COMPOSER);
88 mBufferQueue->setDefaultBufferFormat(fbDev->format);
89 mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height);
90 mBufferQueue->setSynchronousMode(true);
91 mBufferQueue->setBufferCountServer(NUM_FRAME_BUFFERS);
92 setISurfaceTexture(mBufferQueue);
93}
94
95void FramebufferSurface::onFirstRef() {
96 class Listener : public BufferQueue::ConsumerListener {
97 const wp<FramebufferSurface> that;
98 virtual ~Listener() { }
99 virtual void onBuffersReleased() { }
100 void onFrameAvailable() {
101 sp<FramebufferSurface> self = that.promote();
102 if (self != NULL) {
103 BufferQueue::BufferItem item;
104 status_t err = self->mBufferQueue->acquireBuffer(&item);
105 if (err == 0) {
106 if (item.mGraphicBuffer != 0) {
107 self->mBuffers[item.mBuf] = item.mGraphicBuffer;
108 }
109 self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
110 if (self->mCurrentBufferIndex >= 0) {
111 self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,
Jesse Hallef194142012-06-14 14:45:17 -0700112 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
Mathias Agopian3e876012012-06-07 17:52:54 -0700113 }
114 self->mCurrentBufferIndex = item.mBuf;
115 }
116 }
117 }
118 public:
119 Listener(const sp<FramebufferSurface>& that) : that(that) { }
120 };
121
122 mBufferQueue->setConsumerName(String8("FramebufferSurface"));
123 mBufferQueue->consumerConnect(new Listener(this));
124}
125
126FramebufferSurface::~FramebufferSurface() {
127 if (fbDev) {
128 framebuffer_close(fbDev);
129 }
130}
131
132status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
133{
134 if (!mUpdateOnDemand) {
135 return INVALID_OPERATION;
136 }
137 return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
138}
139
140status_t FramebufferSurface::compositionComplete()
141{
142 if (fbDev->compositionComplete) {
143 return fbDev->compositionComplete(fbDev);
144 }
145 return INVALID_OPERATION;
146}
147
148void FramebufferSurface::dump(String8& result) {
149 if (fbDev->common.version >= 1 && fbDev->dump) {
150 const size_t SIZE = 4096;
151 char buffer[SIZE];
152
153 fbDev->dump(fbDev, buffer, SIZE);
154 result.append(buffer);
155 }
156}
157
158int FramebufferSurface::query(int what, int* value) const {
159 Mutex::Autolock _l(mLock);
160 framebuffer_device_t* fb = fbDev;
161 switch (what) {
162 case NATIVE_WINDOW_DEFAULT_WIDTH:
163 case NATIVE_WINDOW_WIDTH:
164 *value = fb->width;
165 return NO_ERROR;
166 case NATIVE_WINDOW_DEFAULT_HEIGHT:
167 case NATIVE_WINDOW_HEIGHT:
168 *value = fb->height;
169 return NO_ERROR;
170 case NATIVE_WINDOW_FORMAT:
171 *value = fb->format;
172 return NO_ERROR;
173 case NATIVE_WINDOW_CONCRETE_TYPE:
174 *value = NATIVE_WINDOW_FRAMEBUFFER;
175 return NO_ERROR;
176 case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
177 *value = 0;
178 return NO_ERROR;
179 case NATIVE_WINDOW_TRANSFORM_HINT:
180 *value = 0;
181 return NO_ERROR;
182 }
183 return SurfaceTextureClient::query(what, value);
184}
185
186// ----------------------------------------------------------------------------
187}; // namespace android
188// ----------------------------------------------------------------------------