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