blob: 83ebd7a617d35abbae5c4ef77b677b9eca3979ad [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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#include <math.h>
21
22#include <cutils/properties.h>
23
Mathias Agopian076b1cc2009-04-10 14:24:30 -070024#include <utils/RefBase.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025#include <utils/Log.h>
26
Mathias Agopian076b1cc2009-04-10 14:24:30 -070027#include <ui/PixelFormat.h>
Mathias Agopian0926f502009-05-04 14:17:04 -070028#include <ui/FramebufferNativeWindow.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080029
30#include <GLES/gl.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070031#include <EGL/egl.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032#include <EGL/eglext.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070033#include <EGL/android_natives.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034
Mathias Agopian076b1cc2009-04-10 14:24:30 -070035#include <pixelflinger/pixelflinger.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036
37#include "DisplayHardware/DisplayHardware.h"
38
39#include <hardware/copybit.h>
40#include <hardware/overlay.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070041#include <hardware/gralloc.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042
43using namespace android;
44
45static __attribute__((noinline))
46const char *egl_strerror(EGLint err)
47{
48 switch (err){
49 case EGL_SUCCESS: return "EGL_SUCCESS";
50 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
51 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
52 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
53 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
54 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
55 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
56 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
57 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
58 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
59 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
60 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
61 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
62 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
63 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
64 default: return "UNKNOWN";
65 }
66}
67
68static __attribute__((noinline))
69void checkGLErrors()
70{
71 GLenum error = glGetError();
72 if (error != GL_NO_ERROR)
73 LOGE("GL error 0x%04x", int(error));
74}
75
76static __attribute__((noinline))
77void checkEGLErrors(const char* token)
78{
79 EGLint error = eglGetError();
80 // GLESonGL seems to be returning 0 when there is no errors?
81 if (error && error != EGL_SUCCESS)
82 LOGE("%s error 0x%04x (%s)",
83 token, int(error), egl_strerror(error));
84}
85
86
87/*
88 * Initialize the display to the specified values.
89 *
90 */
91
92DisplayHardware::DisplayHardware(
93 const sp<SurfaceFlinger>& flinger,
94 uint32_t dpy)
95 : DisplayHardwareBase(flinger, dpy)
96{
97 init(dpy);
98}
99
100DisplayHardware::~DisplayHardware()
101{
102 fini();
103}
104
105float DisplayHardware::getDpiX() const { return mDpiX; }
106float DisplayHardware::getDpiY() const { return mDpiY; }
107float DisplayHardware::getDensity() const { return mDensity; }
108float DisplayHardware::getRefreshRate() const { return mRefreshRate; }
109int DisplayHardware::getWidth() const { return mWidth; }
110int DisplayHardware::getHeight() const { return mHeight; }
111PixelFormat DisplayHardware::getFormat() const { return mFormat; }
112
113void DisplayHardware::init(uint32_t dpy)
114{
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700115 hw_module_t const* module;
116
117 mNativeWindow = new FramebufferNativeWindow();
118
119 mOverlayEngine = NULL;
120 if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
121 overlay_control_open(module, &mOverlayEngine);
122 }
123
124 framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
125
126 PixelFormatInfo fbFormatInfo;
127 getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo);
128
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800129 // initialize EGL
130 const EGLint attribs[] = {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700131 EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800132 EGL_DEPTH_SIZE, 0,
133 EGL_NONE
134 };
135 EGLint w, h, dummy;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700136 EGLint numConfigs=0, n=0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137 EGLSurface surface;
138 EGLContext context;
139 mFlags = 0;
140
141 // TODO: all the extensions below should be queried through
142 // eglGetProcAddress().
143
144 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
145 eglInitialize(display, NULL, NULL);
146 eglGetConfigs(display, NULL, 0, &numConfigs);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700147
148 // Get all the "potential match" configs...
149 EGLConfig* const configs = new EGLConfig[numConfigs];
150 eglChooseConfig(display, attribs, configs, numConfigs, &n);
151 LOGE_IF(n<=0, "no EGLConfig available!");
152 EGLConfig config = configs[0];
153 if (n > 1) {
154 // if there is more than one candidate, go through the list
155 // and pick one that matches our framebuffer format
156 int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA);
157 int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED);
158 int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN);
159 int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE);
160 for (int i=0 ; i<n ; i++) {
161 EGLint r,g,b,a;
162 eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r);
163 eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g);
164 eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b);
165 eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a);
166 if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) {
167 config = configs[i];
168 }
169 }
170 }
171 delete [] configs;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172
173 /*
174 * Gather EGL extensions
175 */
176
177 const char* const egl_extensions = eglQueryString(
178 display, EGL_EXTENSIONS);
179
180 LOGI("EGL informations:");
181 LOGI("# of configs : %d", numConfigs);
182 LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
183 LOGI("version : %s", eglQueryString(display, EGL_VERSION));
184 LOGI("extensions: %s", egl_extensions);
185 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
186
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800187 // TODO: get the real "update_on_demand" behavior (probably should be HAL module)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700188 // FIXME: mFlags |= UPDATE_ON_DEMAND;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800189
190 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
191 if (dummy == EGL_SLOW_CONFIG)
192 mFlags |= SLOW_CONFIG;
193 }
194
195 /*
196 * Create our main surface
197 */
198
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700199
200 surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
201 checkEGLErrors("eglCreateDisplaySurfaceANDROID");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800202
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700203
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800204 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
205 if (dummy == EGL_BUFFER_PRESERVED) {
206 mFlags |= BUFFER_PRESERVED;
207 }
208 }
209
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700210 mDpiX = mNativeWindow->xdpi;
211 mDpiX = mNativeWindow->ydpi;
212 mRefreshRate = mNativeWindow->getDevice()->fps;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800213
214 char property[PROPERTY_VALUE_MAX];
215 if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
216 LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
217 strcpy(property, "160");
218 }
219 mDensity = atoi(property) * (1.0f/160.0f);
220
221
222 /*
223 * Create our OpenGL ES context
224 */
225
226 context = eglCreateContext(display, config, NULL, NULL);
227 //checkEGLErrors("eglCreateContext");
228
229 eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
230 eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
231
232
233 /*
234 * Gather OpenGL ES extensions
235 */
236
237 eglMakeCurrent(display, surface, surface, context);
238 const char* const gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
239 LOGI("OpenGL informations:");
240 LOGI("vendor : %s", glGetString(GL_VENDOR));
241 LOGI("renderer : %s", glGetString(GL_RENDERER));
242 LOGI("version : %s", glGetString(GL_VERSION));
243 LOGI("extensions: %s", gl_extensions);
244
245 if (strstr(gl_extensions, "GL_ARB_texture_non_power_of_two")) {
246 mFlags |= NPOT_EXTENSION;
247 }
248 if (strstr(gl_extensions, "GL_OES_draw_texture")) {
249 mFlags |= DRAW_TEXTURE_EXTENSION;
250 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 if (strstr( gl_extensions, "GL_OES_EGL_image") &&
252 (strstr(egl_extensions, "KHR_image_base") ||
253 strstr(egl_extensions, "EGL_KHR_image")) &&
254 strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800255 mFlags |= DIRECT_TEXTURE;
256 }
257
258 // Unbind the context from this thread
259 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
260
261 mDisplay = display;
262 mConfig = config;
263 mSurface = surface;
264 mContext = context;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700265 mFormat = fbDev->format;
266 mPageFlipCount = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800267}
268
269/*
270 * Clean up. Throw out our local state.
271 *
272 * (It's entirely possible we'll never get here, since this is meant
273 * for real hardware, which doesn't restart.)
274 */
275
276void DisplayHardware::fini()
277{
278 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
279 eglTerminate(mDisplay);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800280 overlay_control_close(mOverlayEngine);
281}
282
283void DisplayHardware::releaseScreen() const
284{
285 DisplayHardwareBase::releaseScreen();
286}
287
288void DisplayHardware::acquireScreen() const
289{
290 DisplayHardwareBase::acquireScreen();
291}
292
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800293uint32_t DisplayHardware::getPageFlipCount() const {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700294 return mPageFlipCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800295}
296
297/*
298 * "Flip" the front and back buffers.
299 */
300
301void DisplayHardware::flip(const Region& dirty) const
302{
303 checkGLErrors();
304
305 EGLDisplay dpy = mDisplay;
306 EGLSurface surface = mSurface;
307
308 Region newDirty(dirty);
309 newDirty.andSelf(Rect(mWidth, mHeight));
310
311 if (mFlags & BUFFER_PRESERVED) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800312 mDirty = newDirty;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800313 }
314
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700315 const Rect& b(newDirty.bounds());
Mathias Agopian0926f502009-05-04 14:17:04 -0700316 mNativeWindow->setSwapRectangle(b);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700318 mPageFlipCount++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800319 eglSwapBuffers(dpy, surface);
320 checkEGLErrors("eglSwapBuffers");
321
322 // for debugging
323 //glClearColor(1,0,0,0);
324 //glClear(GL_COLOR_BUFFER_BIT);
325}
326
327uint32_t DisplayHardware::getFlags() const
328{
329 return mFlags;
330}
331
332void DisplayHardware::makeCurrent() const
333{
334 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
335}
336
337void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700338 // FIXME: we need to get rid of this
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339}
340
341void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700342 // FIXME: we need to get rid of this
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800343}