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