blob: 971189f29f5f7238cd1f232007a539254839502b [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -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
17#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <math.h>
23
24#include <cutils/properties.h>
25
26#include <utils/Log.h>
27
28#include <ui/EGLDisplaySurface.h>
29
30#include <GLES/gl.h>
31#include <EGL/eglext.h>
32
33
34#include "DisplayHardware/DisplayHardware.h"
35
36#include <hardware/copybit.h>
37#include <hardware/overlay.h>
38
39using namespace android;
40
41static __attribute__((noinline))
42const char *egl_strerror(EGLint err)
43{
44 switch (err){
45 case EGL_SUCCESS: return "EGL_SUCCESS";
46 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
47 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
48 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
49 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
50 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
51 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
52 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
53 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
54 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
55 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
56 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
57 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
58 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
59 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
60 default: return "UNKNOWN";
61 }
62}
63
64static __attribute__((noinline))
65void checkGLErrors()
66{
67 GLenum error = glGetError();
68 if (error != GL_NO_ERROR)
69 LOGE("GL error 0x%04x", int(error));
70}
71
72static __attribute__((noinline))
73void checkEGLErrors(const char* token)
74{
75 EGLint error = eglGetError();
76 // GLESonGL seems to be returning 0 when there is no errors?
77 if (error && error != EGL_SUCCESS)
78 LOGE("%s error 0x%04x (%s)",
79 token, int(error), egl_strerror(error));
80}
81
82
83/*
84 * Initialize the display to the specified values.
85 *
86 */
87
88DisplayHardware::DisplayHardware(
89 const sp<SurfaceFlinger>& flinger,
90 uint32_t dpy)
91 : DisplayHardwareBase(flinger, dpy)
92{
93 init(dpy);
94}
95
96DisplayHardware::~DisplayHardware()
97{
98 fini();
99}
100
101float DisplayHardware::getDpiX() const { return mDpiX; }
102float DisplayHardware::getDpiY() const { return mDpiY; }
103float DisplayHardware::getDensity() const { return mDensity; }
104float DisplayHardware::getRefreshRate() const { return mRefreshRate; }
105int DisplayHardware::getWidth() const { return mWidth; }
106int DisplayHardware::getHeight() const { return mHeight; }
107PixelFormat DisplayHardware::getFormat() const { return mFormat; }
108
109void DisplayHardware::init(uint32_t dpy)
110{
111 // initialize EGL
112 const EGLint attribs[] = {
113 EGL_RED_SIZE, 5,
114 EGL_GREEN_SIZE, 6,
115 EGL_BLUE_SIZE, 5,
116 EGL_DEPTH_SIZE, 0,
117 EGL_NONE
118 };
119 EGLint w, h, dummy;
120 EGLint numConfigs, n;
121 EGLConfig config;
122 EGLSurface surface;
123 EGLContext context;
124 mFlags = 0;
125
126 // TODO: all the extensions below should be queried through
127 // eglGetProcAddress().
128
129 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
130 eglInitialize(display, NULL, NULL);
131 eglGetConfigs(display, NULL, 0, &numConfigs);
132 eglChooseConfig(display, attribs, &config, 1, &n);
133
134 /*
135 * Gather EGL extensions
136 */
137
138 const char* const egl_extensions = eglQueryString(
139 display, EGL_EXTENSIONS);
140
141 LOGI("EGL informations:");
142 LOGI("# of configs : %d", numConfigs);
143 LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
144 LOGI("version : %s", eglQueryString(display, EGL_VERSION));
145 LOGI("extensions: %s", egl_extensions);
146 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
147
148 // TODO: get this from the devfb driver (probably should be HAL module)
149 mFlags |= SWAP_RECTANGLE_EXTENSION;
150
151 // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
152 mFlags |= UPDATE_ON_DEMAND;
153
154 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
155 if (dummy == EGL_SLOW_CONFIG)
156 mFlags |= SLOW_CONFIG;
157 }
158
159 /*
160 * Create our main surface
161 */
162
163 mDisplaySurface = new EGLDisplaySurface();
164
165 surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
166 //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
167
168 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
169 if (dummy == EGL_BUFFER_PRESERVED) {
170 mFlags |= BUFFER_PRESERVED;
171 }
172 }
173
174 GLint value = EGL_UNKNOWN;
175 eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
176 if (value == EGL_UNKNOWN) {
177 mDpiX = 160.0f;
178 } else {
179 mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
180 }
181 value = EGL_UNKNOWN;
182 eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
183 if (value == EGL_UNKNOWN) {
184 mDpiY = 160.0f;
185 } else {
186 mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
187 }
188 mRefreshRate = 60.f; // TODO: get the real refresh rate
189
190
191 char property[PROPERTY_VALUE_MAX];
192 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
193 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
194 strcpy(property, "160");
195 }
David 'Digit' Turner694e10b2009-06-18 04:30:32 +0200196
197 /* Override the property value if qemu.sf.lcd_density is defined. */
198 {
199 char qemu_property[PROPERTY_VALUE_MAX];
200 if (property_get("qemu.sf.lcd_density", qemu_property, NULL) > 0) {
201 strlcpy(property, qemu_property, sizeof property);
202 }
203 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800204 mDensity = atoi(property) * (1.0f/160.0f);
205
206
207 /*
208 * Create our OpenGL ES context
209 */
210
211 context = eglCreateContext(display, config, NULL, NULL);
212 //checkEGLErrors("eglCreateContext");
213
214 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
215 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
216
217
218 /*
219 * Gather OpenGL ES extensions
220 */
221
222 eglMakeCurrent(display, surface, surface, context);
223 const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
224 LOGI("OpenGL informations:");
225 LOGI("vendor : %s", glGetString(GL_VENDOR));
226 LOGI("renderer : %s", glGetString(GL_RENDERER));
227 LOGI("version : %s", glGetString(GL_VERSION));
228 LOGI("extensions: %s", gl_extensions);
229
230 if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
231 mFlags |= NPOT_EXTENSION;
232 }
233 if (strstr(gl_extensions, "GL_OES_draw_texture")) {
234 mFlags |= DRAW_TEXTURE_EXTENSION;
235 }
236 if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
237 mFlags |= DIRECT_TEXTURE;
238 }
239
240 // Unbind the context from this thread
241 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
242
243 mDisplay = display;
244 mConfig = config;
245 mSurface = surface;
246 mContext = context;
247 mFormat = GGL_PIXEL_FORMAT_RGB_565;
248
249 hw_module_t const* module;
250
251 mBlitEngine = NULL;
252 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
253 copybit_open(module, &mBlitEngine);
254 }
255
256 mOverlayEngine = NULL;
257 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
258 overlay_control_open(module, &mOverlayEngine);
259 }
260}
261
262/*
263 * Clean up. Throw out our local state.
264 *
265 * (It's entirely possible we'll never get here, since this is meant
266 * for real hardware, which doesn't restart.)
267 */
268
269void DisplayHardware::fini()
270{
271 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
272 eglTerminate(mDisplay);
273 copybit_close(mBlitEngine);
274 overlay_control_close(mOverlayEngine);
275}
276
277void DisplayHardware::releaseScreen() const
278{
279 DisplayHardwareBase::releaseScreen();
280}
281
282void DisplayHardware::acquireScreen() const
283{
284 DisplayHardwareBase::acquireScreen();
285}
286
287void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
288{
289 img->w = mDisplaySurface->stride;
290 img->h = mDisplaySurface->height;
291 img->format = mDisplaySurface->format;
292 img->offset = mDisplaySurface->offset;
293 img->base = (void*)mDisplaySurface->base;
294 img->fd = mDisplaySurface->fd;
295}
296
297void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
298{
299 fb->version= sizeof(GGLSurface);
300 fb->width = mDisplaySurface->width;
301 fb->height = mDisplaySurface->height;
302 fb->stride = mDisplaySurface->stride;
303 fb->format = mDisplaySurface->format;
304 fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
305}
306
307uint32_t DisplayHardware::getPageFlipCount() const {
308 return mDisplaySurface->getPageFlipCount();
309}
310
311/*
312 * "Flip" the front and back buffers.
313 */
314
315void DisplayHardware::flip(const Region& dirty) const
316{
317 checkGLErrors();
318
319 EGLDisplay dpy = mDisplay;
320 EGLSurface surface = mSurface;
321
322 Region newDirty(dirty);
323 newDirty.andSelf(Rect(mWidth, mHeight));
324
325 if (mFlags & BUFFER_PRESERVED) {
326 const Region copyback(mDirty.subtract(newDirty));
327 mDirty = newDirty;
328 mDisplaySurface->copyFrontToBack(copyback);
329 }
330
331 if (mFlags & SWAP_RECTANGLE_EXTENSION) {
332 const Rect& b(newDirty.bounds());
333 mDisplaySurface->setSwapRectangle(
334 b.left, b.top, b.width(), b.height());
335 }
336
337 eglSwapBuffers(dpy, surface);
338 checkEGLErrors("eglSwapBuffers");
339
340 // for debugging
341 //glClearColor(1,0,0,0);
342 //glClear(GL_COLOR_BUFFER_BIT);
343}
344
345uint32_t DisplayHardware::getFlags() const
346{
347 return mFlags;
348}
349
350void DisplayHardware::makeCurrent() const
351{
352 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
353}
354
355void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
356 mDisplaySurface->copyFrontToImage(front);
357}
358
359void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
360 mDisplaySurface->copyBackToImage(front);
361}