blob: 92588fa0d134c1f84d0cd515f6cab0f2539fbcf0 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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>
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080022#include <math.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070023
24#include <GLES/egl.h>
25
The Android Open Source Project8a7a6752009-01-15 16:12:10 -080026#include <cutils/properties.h>
27
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070028#include <utils/Log.h>
29
30#include <ui/EGLDisplaySurface.h>
31
32#include "DisplayHardware/DisplayHardware.h"
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080033
34#include <hardware/copybit.h>
35#include <hardware/overlay.h>
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070036
37using namespace android;
38
39static __attribute__((noinline))
40const char *egl_strerror(EGLint err)
41{
42 switch (err){
43 case EGL_SUCCESS: return "EGL_SUCCESS";
44 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
45 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
46 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
47 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
48 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
49 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
50 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
51 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
52 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
53 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
54 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
55 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
56 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
57 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
58 default: return "UNKNOWN";
59 }
60}
61
62static __attribute__((noinline))
63void checkGLErrors()
64{
65 GLenum error = glGetError();
66 if (error != GL_NO_ERROR)
67 LOGE("GL error 0x%04x", int(error));
68}
69
70static __attribute__((noinline))
71void checkEGLErrors(const char* token)
72{
73 EGLint error = eglGetError();
74 // GLESonGL seems to be returning 0 when there is no errors?
75 if (error && error != EGL_SUCCESS)
76 LOGE("%s error 0x%04x (%s)",
77 token, int(error), egl_strerror(error));
78}
79
80
81/*
82 * Initialize the display to the specified values.
83 *
84 */
85
86DisplayHardware::DisplayHardware(
87 const sp<SurfaceFlinger>& flinger,
88 uint32_t dpy)
89 : DisplayHardwareBase(flinger, dpy)
90{
91 init(dpy);
92}
93
94DisplayHardware::~DisplayHardware()
95{
96 fini();
97}
98
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080099float DisplayHardware::getDpiX() const { return mDpiX; }
100float DisplayHardware::getDpiY() const { return mDpiY; }
101float DisplayHardware::getDensity() const { return mDensity; }
102float DisplayHardware::getRefreshRate() const { return mRefreshRate; }
103int DisplayHardware::getWidth() const { return mWidth; }
104int DisplayHardware::getHeight() const { return mHeight; }
105PixelFormat DisplayHardware::getFormat() const { return mFormat; }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700106
107void DisplayHardware::init(uint32_t dpy)
108{
109 // initialize EGL
110 const EGLint attribs[] = {
111 EGL_RED_SIZE, 5,
112 EGL_GREEN_SIZE, 6,
113 EGL_BLUE_SIZE, 5,
114 EGL_DEPTH_SIZE, 0,
115 EGL_NONE
116 };
117 EGLint w, h, dummy;
118 EGLint numConfigs, n;
119 EGLConfig config;
120 EGLSurface surface;
121 EGLContext context;
122 mFlags = 0;
123
124 // TODO: all the extensions below should be queried through
125 // eglGetProcAddress().
126
127 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
128 eglInitialize(display, NULL, NULL);
129 eglGetConfigs(display, NULL, 0, &numConfigs);
130 eglChooseConfig(display, attribs, &config, 1, &n);
131
132 /*
133 * Gather EGL extensions
134 */
135
136 const char* const egl_extensions = eglQueryString(
137 display, EGL_EXTENSIONS);
138
139 const char* egl_extensions_config = egl_extensions;
140
141 if (strstr(egl_extensions, "EGL_ANDROID_query_string_config")) {
142 egl_extensions_config = eglQueryStringConfigANDROID(
143 display, config, EGL_EXTENSIONS);
144 }
145
146 LOGI("EGL informations:");
147 LOGI("# of configs : %d", numConfigs);
148 LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
149 LOGI("version : %s", eglQueryString(display, EGL_VERSION));
150 LOGI("extensions: %s", egl_extensions);
151 LOGI("ext/config: %s", egl_extensions_config);
152 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
153
154 if (strstr(egl_extensions_config, "EGL_ANDROID_swap_rectangle")) {
155 mFlags |= SWAP_RECTANGLE_EXTENSION;
156 // TODO: get the real "update_on_demand" behavior
157 mFlags |= UPDATE_ON_DEMAND;
158 }
159 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
160 if (dummy == EGL_SLOW_CONFIG)
161 mFlags |= SLOW_CONFIG;
162 }
163
164 /*
165 * Create our main surface
166 */
167
168 mDisplaySurface = new EGLDisplaySurface();
169
170 surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
171 //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
172
173 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
174 if (dummy == EGL_BUFFER_PRESERVED) {
175 mFlags |= BUFFER_PRESERVED;
176 if (strstr(egl_extensions_config, "EGL_ANDROID_copy_front_to_back")) {
177 mFlags |= COPY_BACK_EXTENSION;
178 }
179 }
180 }
181
182 GLint value = EGL_UNKNOWN;
183 eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
184 if (value == EGL_UNKNOWN) {
185 mDpiX = 160.0f;
186 } else {
187 mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
188 }
189 value = EGL_UNKNOWN;
190 eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
191 if (value == EGL_UNKNOWN) {
192 mDpiY = 160.0f;
193 } else {
194 mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
195 }
196 mRefreshRate = 60.f; // TODO: get the real refresh rate
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800197
The Android Open Source Project8a7a6752009-01-15 16:12:10 -0800198
199 char property[PROPERTY_VALUE_MAX];
200 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
201 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
202 strcpy(property, "160");
203 }
204 mDensity = atoi(property) * (1.0f/160.0f);
205
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700206
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;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800248
249 hw_module_t const* module;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700250
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800251 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) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800258 overlay_control_open(module, &mOverlayEngine);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800259 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700260}
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);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800273 copybit_close(mBlitEngine);
The Android Open Source Project27629322009-01-09 17:51:23 -0800274 overlay_control_close(mOverlayEngine);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700275}
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 eglSwapRectangleANDROID(
334 dpy, surface,
335 b.left, b.top, b.width(), b.height());
336 }
337
338 eglSwapBuffers(dpy, surface);
339 checkEGLErrors("eglSwapBuffers");
340
341 // for debugging
342 //glClearColor(1,0,0,0);
343 //glClear(GL_COLOR_BUFFER_BIT);
344}
345
346uint32_t DisplayHardware::getFlags() const
347{
348 return mFlags;
349}
350
351void DisplayHardware::makeCurrent() const
352{
353 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
354}