blob: eec645edc907a3c452b325d2eae7384aae289b8c [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];
David 'Digit' Turnerae71acc2009-06-19 04:41:12 +0200192 /* Read density from build-specific ro.sf.lcd_density property
193 * except if it is overriden by qemu.sf.lcd_density.
194 */
195 if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
196 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
197 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
198 strcpy(property, "160");
David 'Digit' Turner694e10b2009-06-18 04:30:32 +0200199 }
200 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201 mDensity = atoi(property) * (1.0f/160.0f);
202
203
204 /*
205 * Create our OpenGL ES context
206 */
207
208 context = eglCreateContext(display, config, NULL, NULL);
209 //checkEGLErrors("eglCreateContext");
210
211 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
212 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
213
214
215 /*
216 * Gather OpenGL ES extensions
217 */
218
219 eglMakeCurrent(display, surface, surface, context);
220 const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
221 LOGI("OpenGL informations:");
222 LOGI("vendor : %s", glGetString(GL_VENDOR));
223 LOGI("renderer : %s", glGetString(GL_RENDERER));
224 LOGI("version : %s", glGetString(GL_VERSION));
225 LOGI("extensions: %s", gl_extensions);
226
227 if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
228 mFlags |= NPOT_EXTENSION;
229 }
230 if (strstr(gl_extensions, "GL_OES_draw_texture")) {
231 mFlags |= DRAW_TEXTURE_EXTENSION;
232 }
233 if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) {
234 mFlags |= DIRECT_TEXTURE;
235 }
236
237 // Unbind the context from this thread
238 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
239
240 mDisplay = display;
241 mConfig = config;
242 mSurface = surface;
243 mContext = context;
244 mFormat = GGL_PIXEL_FORMAT_RGB_565;
245
246 hw_module_t const* module;
247
248 mBlitEngine = NULL;
249 if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
250 copybit_open(module, &mBlitEngine);
251 }
252
253 mOverlayEngine = NULL;
254 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
255 overlay_control_open(module, &mOverlayEngine);
256 }
257}
258
259/*
260 * Clean up. Throw out our local state.
261 *
262 * (It's entirely possible we'll never get here, since this is meant
263 * for real hardware, which doesn't restart.)
264 */
265
266void DisplayHardware::fini()
267{
268 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
269 eglTerminate(mDisplay);
270 copybit_close(mBlitEngine);
271 overlay_control_close(mOverlayEngine);
272}
273
274void DisplayHardware::releaseScreen() const
275{
276 DisplayHardwareBase::releaseScreen();
277}
278
279void DisplayHardware::acquireScreen() const
280{
281 DisplayHardwareBase::acquireScreen();
282}
283
284void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
285{
286 img->w = mDisplaySurface->stride;
287 img->h = mDisplaySurface->height;
288 img->format = mDisplaySurface->format;
289 img->offset = mDisplaySurface->offset;
290 img->base = (void*)mDisplaySurface->base;
291 img->fd = mDisplaySurface->fd;
292}
293
294void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
295{
296 fb->version= sizeof(GGLSurface);
297 fb->width = mDisplaySurface->width;
298 fb->height = mDisplaySurface->height;
299 fb->stride = mDisplaySurface->stride;
300 fb->format = mDisplaySurface->format;
301 fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
302}
303
304uint32_t DisplayHardware::getPageFlipCount() const {
305 return mDisplaySurface->getPageFlipCount();
306}
307
308/*
309 * "Flip" the front and back buffers.
310 */
311
312void DisplayHardware::flip(const Region& dirty) const
313{
314 checkGLErrors();
315
316 EGLDisplay dpy = mDisplay;
317 EGLSurface surface = mSurface;
318
319 Region newDirty(dirty);
320 newDirty.andSelf(Rect(mWidth, mHeight));
321
322 if (mFlags & BUFFER_PRESERVED) {
323 const Region copyback(mDirty.subtract(newDirty));
324 mDirty = newDirty;
325 mDisplaySurface->copyFrontToBack(copyback);
326 }
327
328 if (mFlags & SWAP_RECTANGLE_EXTENSION) {
329 const Rect& b(newDirty.bounds());
330 mDisplaySurface->setSwapRectangle(
331 b.left, b.top, b.width(), b.height());
332 }
333
334 eglSwapBuffers(dpy, surface);
335 checkEGLErrors("eglSwapBuffers");
336
337 // for debugging
338 //glClearColor(1,0,0,0);
339 //glClear(GL_COLOR_BUFFER_BIT);
340}
341
342uint32_t DisplayHardware::getFlags() const
343{
344 return mFlags;
345}
346
347void DisplayHardware::makeCurrent() const
348{
349 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
350}
351
352void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
353 mDisplaySurface->copyFrontToImage(front);
354}
355
356void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
357 mDisplaySurface->copyBackToImage(front);
358}