blob: 5dd94464f159c5c13a2657e58b1b0fc9f29fa52a [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>
22
23#include <GLES/egl.h>
24
25#include <utils/Log.h>
26
27#include <ui/EGLDisplaySurface.h>
28
29#include "DisplayHardware/DisplayHardware.h"
30#include "ui/BlitHardware.h"
31
32using namespace android;
33
34static __attribute__((noinline))
35const char *egl_strerror(EGLint err)
36{
37 switch (err){
38 case EGL_SUCCESS: return "EGL_SUCCESS";
39 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED";
40 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS";
41 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC";
42 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE";
43 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG";
44 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT";
45 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
46 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY";
47 case EGL_BAD_MATCH: return "EGL_BAD_MATCH";
48 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
49 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
50 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER";
51 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE";
52 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST";
53 default: return "UNKNOWN";
54 }
55}
56
57static __attribute__((noinline))
58void checkGLErrors()
59{
60 GLenum error = glGetError();
61 if (error != GL_NO_ERROR)
62 LOGE("GL error 0x%04x", int(error));
63}
64
65static __attribute__((noinline))
66void checkEGLErrors(const char* token)
67{
68 EGLint error = eglGetError();
69 // GLESonGL seems to be returning 0 when there is no errors?
70 if (error && error != EGL_SUCCESS)
71 LOGE("%s error 0x%04x (%s)",
72 token, int(error), egl_strerror(error));
73}
74
75
76/*
77 * Initialize the display to the specified values.
78 *
79 */
80
81DisplayHardware::DisplayHardware(
82 const sp<SurfaceFlinger>& flinger,
83 uint32_t dpy)
84 : DisplayHardwareBase(flinger, dpy)
85{
86 init(dpy);
87}
88
89DisplayHardware::~DisplayHardware()
90{
91 fini();
92}
93
94float DisplayHardware::getDpiX() const { return mDpiX; }
95float DisplayHardware::getDpiY() const { return mDpiY; }
96float DisplayHardware::getRefreshRate() const { return mRefreshRate; }
97
98int DisplayHardware::getWidth() const {
99 return mWidth;
100}
101int DisplayHardware::getHeight() const {
102 return mHeight;
103}
104PixelFormat DisplayHardware::getFormat() const {
105 return mFormat;
106}
107
108void DisplayHardware::init(uint32_t dpy)
109{
110 // initialize EGL
111 const EGLint attribs[] = {
112 EGL_RED_SIZE, 5,
113 EGL_GREEN_SIZE, 6,
114 EGL_BLUE_SIZE, 5,
115 EGL_DEPTH_SIZE, 0,
116 EGL_NONE
117 };
118 EGLint w, h, dummy;
119 EGLint numConfigs, n;
120 EGLConfig config;
121 EGLSurface surface;
122 EGLContext context;
123 mFlags = 0;
124
125 // TODO: all the extensions below should be queried through
126 // eglGetProcAddress().
127
128 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
129 eglInitialize(display, NULL, NULL);
130 eglGetConfigs(display, NULL, 0, &numConfigs);
131 eglChooseConfig(display, attribs, &config, 1, &n);
132
133 /*
134 * Gather EGL extensions
135 */
136
137 const char* const egl_extensions = eglQueryString(
138 display, EGL_EXTENSIONS);
139
140 const char* egl_extensions_config = egl_extensions;
141
142 if (strstr(egl_extensions, "EGL_ANDROID_query_string_config")) {
143 egl_extensions_config = eglQueryStringConfigANDROID(
144 display, config, EGL_EXTENSIONS);
145 }
146
147 LOGI("EGL informations:");
148 LOGI("# of configs : %d", numConfigs);
149 LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
150 LOGI("version : %s", eglQueryString(display, EGL_VERSION));
151 LOGI("extensions: %s", egl_extensions);
152 LOGI("ext/config: %s", egl_extensions_config);
153 LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
154
155 if (strstr(egl_extensions_config, "EGL_ANDROID_swap_rectangle")) {
156 mFlags |= SWAP_RECTANGLE_EXTENSION;
157 // TODO: get the real "update_on_demand" behavior
158 mFlags |= UPDATE_ON_DEMAND;
159 }
160 if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) {
161 if (dummy == EGL_SLOW_CONFIG)
162 mFlags |= SLOW_CONFIG;
163 }
164
165 /*
166 * Create our main surface
167 */
168
169 mDisplaySurface = new EGLDisplaySurface();
170
171 surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL);
172 //checkEGLErrors("eglCreateDisplaySurfaceANDROID");
173
174 if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
175 if (dummy == EGL_BUFFER_PRESERVED) {
176 mFlags |= BUFFER_PRESERVED;
177 if (strstr(egl_extensions_config, "EGL_ANDROID_copy_front_to_back")) {
178 mFlags |= COPY_BACK_EXTENSION;
179 }
180 }
181 }
182
183 GLint value = EGL_UNKNOWN;
184 eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value);
185 if (value == EGL_UNKNOWN) {
186 mDpiX = 160.0f;
187 } else {
188 mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING;
189 }
190 value = EGL_UNKNOWN;
191 eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value);
192 if (value == EGL_UNKNOWN) {
193 mDpiY = 160.0f;
194 } else {
195 mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING;
196 }
197 mRefreshRate = 60.f; // TODO: get the real refresh rate
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 mBlitEngine = copybit_init();
242}
243
244/*
245 * Clean up. Throw out our local state.
246 *
247 * (It's entirely possible we'll never get here, since this is meant
248 * for real hardware, which doesn't restart.)
249 */
250
251void DisplayHardware::fini()
252{
253 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
254 eglTerminate(mDisplay);
255 copybit_term(mBlitEngine);
256}
257
258void DisplayHardware::releaseScreen() const
259{
260 DisplayHardwareBase::releaseScreen();
261}
262
263void DisplayHardware::acquireScreen() const
264{
265 DisplayHardwareBase::acquireScreen();
266}
267
268void DisplayHardware::getDisplaySurface(copybit_image_t* img) const
269{
270 img->w = mDisplaySurface->stride;
271 img->h = mDisplaySurface->height;
272 img->format = mDisplaySurface->format;
273 img->offset = mDisplaySurface->offset;
274 img->base = (void*)mDisplaySurface->base;
275 img->fd = mDisplaySurface->fd;
276}
277
278void DisplayHardware::getDisplaySurface(GGLSurface* fb) const
279{
280 fb->version= sizeof(GGLSurface);
281 fb->width = mDisplaySurface->width;
282 fb->height = mDisplaySurface->height;
283 fb->stride = mDisplaySurface->stride;
284 fb->format = mDisplaySurface->format;
285 fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset;
286}
287
288uint32_t DisplayHardware::getPageFlipCount() const {
289 return mDisplaySurface->getPageFlipCount();
290}
291
292/*
293 * "Flip" the front and back buffers.
294 */
295
296void DisplayHardware::flip(const Region& dirty) const
297{
298 checkGLErrors();
299
300 EGLDisplay dpy = mDisplay;
301 EGLSurface surface = mSurface;
302
303 Region newDirty(dirty);
304 newDirty.andSelf(Rect(mWidth, mHeight));
305
306 if (mFlags & BUFFER_PRESERVED) {
307 const Region copyback(mDirty.subtract(newDirty));
308 mDirty = newDirty;
309 mDisplaySurface->copyFrontToBack(copyback);
310 }
311
312 if (mFlags & SWAP_RECTANGLE_EXTENSION) {
313 const Rect& b(newDirty.bounds());
314 eglSwapRectangleANDROID(
315 dpy, surface,
316 b.left, b.top, b.width(), b.height());
317 }
318
319 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}