diff options
122 files changed, 10154 insertions, 4860 deletions
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 9c94c2e..d31d81c 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -12,6 +12,8 @@ ifeq ($(TARGET_SIMULATOR),true) endif endif +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index d565dc1..e2d01de 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "BootAnimation" - #include <stdint.h> #include <sys/types.h> #include <math.h> @@ -35,7 +33,7 @@ #include <ui/DisplayInfo.h> #include <ui/ISurfaceComposer.h> #include <ui/ISurfaceFlingerClient.h> -#include <ui/EGLNativeWindowSurface.h> +#include <ui/FramebufferNativeWindow.h> #include <core/SkBitmap.h> #include <images/SkImageDecoder.h> @@ -130,12 +128,15 @@ status_t BootAnimation::readyToRun() { return -1; // create the native surface - sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, - PIXEL_FORMAT_RGB_565, ISurfaceComposer::eGPU); + sp<SurfaceControl> control = session()->createSurface( + getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565, + ISurfaceComposer::eGPU); session()->openTransaction(); - s->setLayer(0x40000000); + control->setLayer(0x40000000); session()->closeTransaction(); + sp<Surface> s = control->getSurface(); + // initialize opengl and egl const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE }; @@ -150,9 +151,7 @@ status_t BootAnimation::readyToRun() { eglInitialize(display, 0, 0); eglChooseConfig(display, attribs, &config, 1, &numConfigs); - mNativeWindowSurface = new EGLNativeWindowSurface(s); - surface = eglCreateWindowSurface(display, config, - mNativeWindowSurface.get(), NULL); + surface = eglCreateWindowSurface(display, config, s.get(), NULL); context = eglCreateContext(display, config, NULL, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &w); @@ -163,6 +162,7 @@ status_t BootAnimation::readyToRun() { mSurface = surface; mWidth = w; mHeight = h; + mFlingerSurfaceControl = control; mFlingerSurface = s; // initialize GL @@ -178,8 +178,8 @@ bool BootAnimation::threadLoop() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); - mNativeWindowSurface.clear(); mFlingerSurface.clear(); + mFlingerSurfaceControl.clear(); eglTerminate(mDisplay); IPCThreadState::self()->stopProcess(); return r; @@ -200,8 +200,7 @@ bool BootAnimation::android() { const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); // draw and update only what we need - mNativeWindowSurface->setSwapRectangle(updateRect.left, - updateRect.top, updateRect.width(), updateRect.height()); + mFlingerSurface->setSwapRectangle(updateRect); glEnable(GL_SCISSOR_TEST); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 42e9eed..796077d 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -34,7 +34,6 @@ class SkBitmap; namespace android { class AssetManager; -class EGLNativeWindowSurface; // --------------------------------------------------------------------------- @@ -68,8 +67,8 @@ private: EGLDisplay mDisplay; EGLDisplay mContext; EGLDisplay mSurface; + sp<SurfaceControl> mFlingerSurfaceControl; sp<Surface> mFlingerSurface; - sp<EGLNativeWindowSurface> mNativeWindowSurface; }; // --------------------------------------------------------------------------- diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 0178d63..a87c622 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -127,6 +127,8 @@ public class Surface implements Parcelable { @SuppressWarnings("unused") private int mSurface; @SuppressWarnings("unused") + private int mSurfaceControl; + @SuppressWarnings("unused") private int mSaveCount; @SuppressWarnings("unused") private Canvas mCanvas; @@ -270,7 +272,7 @@ public class Surface implements Parcelable { @Override public String toString() { - return "Surface(native-token=" + mSurface + ")"; + return "Surface(native-token=" + mSurfaceControl + ")"; } private Surface(Parcel source) throws OutOfResourcesException { @@ -283,7 +285,7 @@ public class Surface implements Parcelable { public native void readFromParcel(Parcel source); public native void writeToParcel(Parcel dest, int flags); - + public static final Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { @@ -304,7 +306,7 @@ public class Surface implements Parcelable { /* no user serviceable parts here ... */ @Override protected void finalize() throws Throwable { - clear(); + release(); } private native void init(SurfaceSession s, @@ -312,4 +314,6 @@ public class Surface implements Parcelable { throws OutOfResourcesException; private native void init(Parcel source); + + private native void release(); } diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 31cc4f7..f6f4c70 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -15,6 +15,8 @@ ifneq ($(USE_CUSTOM_RUNTIME_HEAP_MAX),) LOCAL_CFLAGS += -DCUSTOM_RUNTIME_HEAP_MAX=$(USE_CUSTOM_RUNTIME_HEAP_MAX) endif +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + LOCAL_SRC_FILES:= \ ActivityManager.cpp \ AndroidRuntime.cpp \ diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 076775f..bd3c805 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -24,6 +24,7 @@ #include <SkCanvas.h> #include <SkBitmap.h> +#include <SkRegion.h> #include "jni.h" #include <android_runtime/AndroidRuntime.h> @@ -45,6 +46,7 @@ struct sso_t { static sso_t sso; struct so_t { + jfieldID surfaceControl; jfieldID surface; jfieldID saveCount; jfieldID canvas; @@ -121,10 +123,50 @@ static void SurfaceSession_kill(JNIEnv* env, jobject clazz) // ---------------------------------------------------------------------------- +static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz) +{ + SurfaceControl* const p = + (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); + return sp<SurfaceControl>(p); +} + +static void setSurfaceControl(JNIEnv* env, jobject clazz, + const sp<SurfaceControl>& surface) +{ + SurfaceControl* const p = + (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); + if (surface.get()) { + surface->incStrong(clazz); + } + if (p) { + p->decStrong(clazz); + } + env->SetIntField(clazz, so.surfaceControl, (int)surface.get()); +} + static sp<Surface> getSurface(JNIEnv* env, jobject clazz) { - Surface* const p = (Surface*)env->GetIntField(clazz, so.surface); - return sp<Surface>(p); + sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface)); + if (result == 0) { + /* + * if this method is called from the WindowManager's process, it means + * the client is is not remote, and therefore is allowed to have + * a Surface (data), so we create it here. + * If we don't have a SurfaceControl, it means we're in a different + * process. + */ + + SurfaceControl* const control = + (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); + if (control) { + result = control->getSurface(); + if (result != 0) { + result->incStrong(clazz); + env->SetIntField(clazz, so.surface, (int)result.get()); + } + } + } + return result; } static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface) @@ -153,12 +195,12 @@ static void Surface_init( SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client); - sp<Surface> surface(client->createSurface(pid, dpy, w, h, format, flags)); + sp<SurfaceControl> surface(client->createSurface(pid, dpy, w, h, format, flags)); if (surface == 0) { doThrow(env, OutOfResourcesException); return; } - setSurface(env, clazz, surface); + setSurfaceControl(env, clazz, surface); } static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) @@ -168,19 +210,34 @@ static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) doThrow(env, "java/lang/NullPointerException", NULL); return; } - const sp<Surface>& rhs = Surface::readFromParcel(parcel); + sp<Surface> rhs = new Surface(*parcel); setSurface(env, clazz, rhs); } static void Surface_clear(JNIEnv* env, jobject clazz, uintptr_t *ostack) { + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (SurfaceControl::isValid(surface)) { + surface->clear(); + } + setSurfaceControl(env, clazz, 0); + setSurface(env, clazz, 0); +} + +static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack) +{ + setSurfaceControl(env, clazz, 0); setSurface(env, clazz, 0); } static jboolean Surface_isValid(JNIEnv* env, jobject clazz) { - const sp<Surface>& surface = getSurface(env, clazz); - return surface->isValid() ? JNI_TRUE : JNI_FALSE; + const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz)); + if (surfaceControl != 0) { + return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; + } + const sp<Surface>& surface(getSurface(env, clazz)); + return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; } static inline SkBitmap::Config convertPixelFormat(PixelFormat format) @@ -200,8 +257,8 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) { - const sp<Surface>& surface = getSurface(env, clazz); - if (!surface->isValid()) + const sp<Surface>& surface(getSurface(env, clazz)); + if (!Surface::isValid(surface)) return 0; // get dirty region @@ -212,7 +269,7 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) dirty.top = env->GetIntField(dirtyRect, ro.t); dirty.right = env->GetIntField(dirtyRect, ro.r); dirty.bottom= env->GetIntField(dirtyRect, ro.b); - if (dirty.left < dirty.right && dirty.top < dirty.bottom) { + if (!dirty.isEmpty()) { dirtyRegion.set(dirty); } } else { @@ -235,7 +292,8 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); SkBitmap bitmap; - bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, info.bpr); + ssize_t bpr = info.s * bytesPerPixel(info.format); + bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); if (info.w > 0 && info.h > 0) { bitmap.setPixels(info.bits); } else { @@ -243,13 +301,27 @@ static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) bitmap.setPixels(NULL); } nativeCanvas->setBitmapDevice(bitmap); - nativeCanvas->clipRegion(dirtyRegion.toSkRegion()); + + SkRegion clipReg; + if (dirtyRegion.isRect()) { // very common case + const Rect& b(dirtyRegion.getBounds()); + clipReg.setRect(b.left, b.top, b.right, b.bottom); + } else { + size_t count; + Rect const* r = dirtyRegion.getArray(&count); + while (count) { + clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op); + r++, count--; + } + } + + nativeCanvas->clipRegion(clipReg); int saveCount = nativeCanvas->save(); env->SetIntField(clazz, so.saveCount, saveCount); if (dirtyRect) { - Rect bounds(dirtyRegion.bounds()); + const Rect& bounds(dirtyRegion.getBounds()); env->SetIntField(dirtyRect, ro.l, bounds.left); env->SetIntField(dirtyRect, ro.t, bounds.top); env->SetIntField(dirtyRect, ro.r, bounds.right); @@ -268,8 +340,8 @@ static void Surface_unlockCanvasAndPost( return; } - const sp<Surface>& surface = getSurface(env, clazz); - if (!surface->isValid()) + const sp<Surface>& surface(getSurface(env, clazz)); + if (!Surface::isValid(surface)) return; // detach the canvas from the surface @@ -289,26 +361,8 @@ static void Surface_unlockCanvasAndPost( static void Surface_unlockCanvas( JNIEnv* env, jobject clazz, jobject argCanvas) { - jobject canvas = env->GetObjectField(clazz, so.canvas); - if (canvas != argCanvas) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - return; - } - - const sp<Surface>& surface = getSurface(env, clazz); - if (!surface->isValid()) - return; - - status_t err = surface->unlock(); - if (err < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - return; - } - SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); - int saveCount = env->GetIntField(clazz, so.saveCount); - nativeCanvas->restoreToCount(saveCount); - nativeCanvas->setBitmapDevice(SkBitmap()); - env->SetIntField(clazz, so.saveCount, 0); + // XXX: this API has been removed + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_openTransaction( @@ -353,138 +407,140 @@ static void Surface_unfreezeDisplay( static void Surface_setLayer( JNIEnv* env, jobject clazz, jint zorder) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setLayer(zorder) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setLayer(zorder); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setPosition( JNIEnv* env, jobject clazz, jint x, jint y) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setPosition(x, y) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setPosition(x, y); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setSize( JNIEnv* env, jobject clazz, jint w, jint h) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setSize(w, h) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setSize(w, h); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_hide( JNIEnv* env, jobject clazz) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->hide() < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->hide(); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_show( JNIEnv* env, jobject clazz) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->show() < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->show(); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_freeze( JNIEnv* env, jobject clazz) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->freeze() < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->freeze(); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_unfreeze( JNIEnv* env, jobject clazz) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->unfreeze() < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->unfreeze(); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setFlags( JNIEnv* env, jobject clazz, jint flags, jint mask) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setFlags(flags, mask) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setFlags(flags, mask); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setTransparentRegion( JNIEnv* env, jobject clazz, jobject argRegion) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region); - if (surface->setTransparentRegionHint(Region(*nativeRegion)) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region); + + const SkIRect& b(nativeRegion->getBounds()); + Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); + if (nativeRegion->isComplex()) { + SkRegion::Iterator it(*nativeRegion); + while (!it.done()) { + const SkIRect& r(it.rect()); + reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); + it.next(); } } + + status_t err = surface->setTransparentRegionHint(reg); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setAlpha( JNIEnv* env, jobject clazz, jfloat alpha) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setAlpha(alpha) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setAlpha(alpha); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setMatrix( JNIEnv* env, jobject clazz, jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setMatrix(dsdx, dtdx, dsdy, dtdy) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } static void Surface_setFreezeTint( JNIEnv* env, jobject clazz, jint tint) { - const sp<Surface>& surface = getSurface(env, clazz); - if (surface->isValid()) { - if (surface->setFreezeTint(tint) < 0) { - doThrow(env, "java/lang/IllegalArgumentException", NULL); - } - } + const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); + if (surface == 0) return; + status_t err = surface->setFreezeTint(tint); + if (err<0 && err!=NO_INIT) + doThrow(env, "java/lang/IllegalArgumentException", NULL); } +// ---------------------------------------------------------------------------- + static void Surface_copyFrom( JNIEnv* env, jobject clazz, jobject other) { @@ -496,16 +552,21 @@ static void Surface_copyFrom( return; } - const sp<Surface>& surface = getSurface(env, clazz); - const sp<Surface>& rhs = getSurface(env, other); - if (!Surface::isSameSurface(surface, rhs)) { + /* + * This is used by the WindowManagerService just after constructing + * a Surface and is necessary for returning the Surface reference to + * the caller. At this point, we should only have a SurfaceControl. + */ + + const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz); + const sp<SurfaceControl>& rhs = getSurfaceControl(env, other); + if (!SurfaceControl::isSameSurface(surface, rhs)) { // we reassign the surface only if it's a different one // otherwise we would loose our client-side state. - setSurface(env, clazz, rhs->dup()); + setSurfaceControl(env, clazz, rhs); } } - static void Surface_readFromParcel( JNIEnv* env, jobject clazz, jobject argParcel) { @@ -515,9 +576,9 @@ static void Surface_readFromParcel( return; } - const sp<Surface>& surface = getSurface(env, clazz); - const sp<Surface>& rhs = Surface::readFromParcel(parcel); - if (!Surface::isSameSurface(surface, rhs)) { + const sp<Surface>& control(getSurface(env, clazz)); + sp<Surface> rhs = new Surface(*parcel); + if (!Surface::isSameSurface(control, rhs)) { // we reassign the surface only if it's a different one // otherwise we would loose our client-side state. setSurface(env, clazz, rhs); @@ -535,8 +596,8 @@ static void Surface_writeToParcel( return; } - const sp<Surface>& surface = getSurface(env, clazz); - Surface::writeToParcel(surface, parcel); + const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); + SurfaceControl::writeSurfaceToParcel(control, parcel); } // ---------------------------------------------------------------------------- @@ -557,7 +618,8 @@ static JNINativeMethod gSurfaceMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"init", "(Landroid/view/SurfaceSession;IIIIII)V", (void*)Surface_init }, {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, - {"clear", "()V", (void*)Surface_clear }, + {"clear", "()V", (void*)Surface_clear }, + {"release", "()V", (void*)Surface_release }, {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom }, {"isValid", "()Z", (void*)Surface_isValid }, {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas }, @@ -586,7 +648,8 @@ static JNINativeMethod gSurfaceMethods[] = { void nativeClassInit(JNIEnv* env, jclass clazz) { - so.surface = env->GetFieldID(clazz, "mSurface", "I"); + so.surface = env->GetFieldID(clazz, "mSurface", "I"); + so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I"); so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I"); so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;"); diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index 4452065..974fc0b 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -21,7 +21,6 @@ #include <EGL/egl.h> #include <GLES/gl.h> -#include <ui/EGLNativeWindowSurface.h> #include <ui/Surface.h> #include <SkBitmap.h> #include <SkPixelRef.h> @@ -338,7 +337,7 @@ not_valid_surface: goto not_valid_surface; jint* base = beginNativeAttribList(_env, attrib_list); - EGLSurface sur = eglCreateWindowSurface(dpy, cnf, new EGLNativeWindowSurface(window), base); + EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window, base); endNativeAttributeList(_env, attrib_list, base); return (jint)sur; } diff --git a/core/res/res/drawable/stat_sys_signal_flightmode.png b/core/res/res/drawable/stat_sys_signal_flightmode.png Binary files differindex 2f4fd4f..2f4fd4f 100644..100755 --- a/core/res/res/drawable/stat_sys_signal_flightmode.png +++ b/core/res/res/drawable/stat_sys_signal_flightmode.png diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h index d057556..6628f75 100644 --- a/include/binder/MemoryDealer.h +++ b/include/binder/MemoryDealer.h @@ -126,13 +126,22 @@ public: mFirst = mLast = newNode; newNode->prev = newNode->next = 0; } else { - insertBefore(mFirst, newNode); + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; } } void insertTail(NODE* newNode) { - if (mLast == 0) insertBeginning(newNode); - else insertAfter(mLast, newNode); + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } } NODE* remove(NODE* node) { diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index 0c7ad46..641961f 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -26,6 +26,7 @@ #endif #include <private/pixelflinger/ggl_context.h> +#include <hardware/copybit.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -39,7 +40,7 @@ class EGLSurfaceManager; class EGLBufferObjectManager; namespace gl { - + struct ogles_context_t; struct matrixx_t; struct transform_t; @@ -96,7 +97,7 @@ struct vec4_t { struct vertex_t { enum { - // these constant matter for our clipping + // these constant matter for our clipping CLIP_L = 0x0001, // clipping flags CLIP_R = 0x0002, CLIP_B = 0x0004, @@ -106,7 +107,7 @@ struct vertex_t { EYE = 0x0040, RESERVED = 0x0080, - + USER_CLIP_0 = 0x0100, // user clipping flags USER_CLIP_1 = 0x0200, USER_CLIP_2 = 0x0400, @@ -121,7 +122,7 @@ struct vertex_t { USER_CLIP_ALL = 0x3F00, CLIP_ALL = 0x3F3F, }; - + // the fields below are arranged to minimize d-cache usage // we group together, by cache-line, the fields most likely to be used @@ -130,7 +131,7 @@ struct vertex_t { vec4_t eye; }; vec4_t clip; - + uint32_t flags; size_t index; // cache tag, and vertex index GLfixed fog; @@ -142,7 +143,7 @@ struct vertex_t { vec4_t color; vec4_t texture[GGL_TEXTURE_UNIT_COUNT]; uint32_t reserved1[4]; - + inline void clear() { flags = index = locked = mru = 0; } @@ -199,7 +200,7 @@ struct array_machine_t { GLenum indicesType; buffer_t const* array_buffer; buffer_t const* element_array_buffer; - + void (*compileElements)(ogles_context_t*, vertex_t*, GLint, GLsizei); void (*compileElement)(ogles_context_t*, vertex_t*, GLint); @@ -410,7 +411,7 @@ struct transform_t { matrixx_t matrix; uint32_t flags; uint32_t ops; - + union { struct { void (*point2)(transform_t const* t, vec4_t*, vec4_t const*); @@ -509,17 +510,17 @@ struct viewport_t { GLint x; GLint y; GLsizei w; - GLsizei h; + GLsizei h; struct { GLint x; GLint y; - } surfaceport; + } surfaceport; struct { GLint x; GLint y; GLsizei w; - GLsizei h; - } scissor; + GLsizei h; + } scissor; }; // ---------------------------------------------------------------------------- @@ -594,6 +595,16 @@ struct prims_t { void (*renderTriangle)(GL, vertex_t*, vertex_t*, vertex_t*); }; +struct copybits_context_t { + // A handle to the blit engine, if it exists, else NULL. + copybit_device_t* blitEngine; + int32_t minScale; + int32_t maxScale; + // File descriptor of current drawing surface, if it's suitable for use as + // a copybits destination, else -1. + int drawSurfaceFd; +}; + struct ogles_context_t { context_t rasterizer; array_machine_t arrays __attribute__((aligned(32))); @@ -617,6 +628,14 @@ struct ogles_context_t { uint32_t transformTextures : 1; EGLSurfaceManager* surfaceManager; EGLBufferObjectManager* bufferObjectManager; + + // copybits is only used if LIBAGL_USE_GRALLOC_COPYBITS is + // defined, but it is always present because ogles_context_t is a public + // struct that is used by clients of libagl. We want the size and offsets + // to stay the same, whether or not LIBAGL_USE_GRALLOC_COPYBITS is defined. + + copybits_context_t copybits; + GLenum error; static inline ogles_context_t* get() { diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h new file mode 100644 index 0000000..6c847ff --- /dev/null +++ b/include/private/ui/RegionHelper.h @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UI_PRIVATE_REGION_HELPER_H +#define ANDROID_UI_PRIVATE_REGION_HELPER_H + +#include <stdint.h> +#include <sys/types.h> + +namespace android { +// ---------------------------------------------------------------------------- + +template<typename RECT> +class region_operator +{ + typedef typename RECT::value_type TYPE; + static const TYPE max_value = 0x7FFFFFF; + +public: + /* + * Common boolean operations: + * value is computed as 0b101 op 0b110 + * other boolean operation are possible, simply compute + * their corresponding value with the above formulae and use + * it when instantiating a region_operator. + */ + static const uint32_t LHS = 0x5; // 0b101 + static const uint32_t RHS = 0x6; // 0b110 + enum { + op_nand = LHS & ~RHS, + op_and = LHS & RHS, + op_or = LHS | RHS, + op_xor = LHS ^ RHS + }; + + struct region { + RECT const* rects; + size_t count; + TYPE dx; + TYPE dy; + inline region(const region& rhs) + : rects(rhs.rects), count(rhs.count), dx(rhs.dx), dy(rhs.dy) { } + inline region(RECT const* r, size_t c) + : rects(r), count(c), dx(), dy() { } + inline region(RECT const* r, size_t c, TYPE dx, TYPE dy) + : rects(r), count(c), dx(dx), dy(dy) { } + }; + + class region_rasterizer { + friend class region_operator; + virtual void operator()(const RECT& rect) = 0; + }; + + inline region_operator(int op, const region& lhs, const region& rhs) + : op_mask(op), spanner(lhs, rhs) + { + } + + void operator()(region_rasterizer& rasterizer) { + RECT current; + do { + SpannerInner spannerInner(spanner.lhs, spanner.rhs); + int inside = spanner.next(current.top, current.bottom); + spannerInner.prepare(inside); + do { + TYPE left, right; + int inside = spannerInner.next(current.left, current.right); + if ((op_mask >> inside) & 1) { + if (current.left < current.right && + current.top < current.bottom) { + rasterizer(current); + } + } + } while(!spannerInner.isDone()); + } while(!spanner.isDone()); + } + +private: + uint32_t op_mask; + + class SpannerBase + { + public: + enum { + lhs_before_rhs = 0, + lhs_after_rhs = 1, + lhs_coincide_rhs = 2 + }; + + protected: + TYPE lhs_head; + TYPE lhs_tail; + TYPE rhs_head; + TYPE rhs_tail; + + inline int next(TYPE& head, TYPE& tail, + bool& more_lhs, bool& more_rhs) + { + int inside; + more_lhs = false; + more_rhs = false; + if (lhs_head < rhs_head) { + inside = lhs_before_rhs; + head = lhs_head; + if (lhs_tail <= rhs_head) { + tail = lhs_tail; + more_lhs = true; + } else { + lhs_head = rhs_head; + tail = rhs_head; + } + } else if (rhs_head < lhs_head) { + inside = lhs_after_rhs; + head = rhs_head; + if (rhs_tail <= lhs_head) { + tail = rhs_tail; + more_rhs = true; + } else { + rhs_head = lhs_head; + tail = lhs_head; + } + } else { + inside = lhs_coincide_rhs; + head = lhs_head; + if (lhs_tail <= rhs_tail) { + tail = rhs_head = lhs_tail; + more_lhs = true; + } + if (rhs_tail <= lhs_tail) { + tail = lhs_head = rhs_tail; + more_rhs = true; + } + } + return inside; + } + }; + + class Spanner : protected SpannerBase + { + friend class region_operator; + region lhs; + region rhs; + + public: + inline Spanner(const region& lhs, const region& rhs) + : lhs(lhs), rhs(rhs) + { + SpannerBase::lhs_head = lhs.rects->top + lhs.dy; + SpannerBase::lhs_tail = lhs.rects->bottom + lhs.dy; + SpannerBase::rhs_head = rhs.rects->top + rhs.dy; + SpannerBase::rhs_tail = rhs.rects->bottom + rhs.dy; + } + + inline bool isDone() const { + return !rhs.count && !lhs.count; + } + + inline int next(TYPE& top, TYPE& bottom) + { + bool more_lhs = false; + bool more_rhs = false; + int inside = SpannerBase::next(top, bottom, more_lhs, more_rhs); + if (more_lhs) { + advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail); + } + if (more_rhs) { + advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail); + } + return inside; + } + + private: + static inline + void advance(region& reg, TYPE& aTop, TYPE& aBottom) { + // got to next span + size_t count = reg.count; + RECT const * rects = reg.rects; + RECT const * const end = rects + count; + const int top = rects->top; + while (rects != end && rects->top == top) { + rects++; + count--; + } + if (rects != end) { + aTop = rects->top + reg.dy; + aBottom = rects->bottom + reg.dy; + } else { + aTop = max_value; + aBottom = max_value; + } + reg.rects = rects; + reg.count = count; + } + }; + + class SpannerInner : protected SpannerBase + { + region lhs; + region rhs; + + public: + inline SpannerInner(const region& lhs, const region& rhs) + : lhs(lhs), rhs(rhs) + { + } + + inline void prepare(int inside) { + SpannerBase::lhs_head = lhs.rects->left + lhs.dx; + SpannerBase::lhs_tail = lhs.rects->right + lhs.dx; + SpannerBase::rhs_head = rhs.rects->left + rhs.dx; + SpannerBase::rhs_tail = rhs.rects->right + rhs.dx; + if (inside == SpannerBase::lhs_before_rhs) { + SpannerBase::rhs_head = max_value; + SpannerBase::rhs_tail = max_value; + } else if (inside == SpannerBase::lhs_after_rhs) { + SpannerBase::lhs_head = max_value; + SpannerBase::lhs_tail = max_value; + } else { + // use both spans + } + } + + inline bool isDone() const { + return SpannerBase::lhs_head == max_value && + SpannerBase::rhs_head == max_value; + } + + inline int next(TYPE& left, TYPE& right) + { + bool more_lhs = false; + bool more_rhs = false; + int inside = SpannerBase::next(left, right, more_lhs, more_rhs); + if (more_lhs) { + advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail); + } + if (more_rhs) { + advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail); + } + return inside; + } + + private: + static inline + void advance(region& reg, TYPE& left, TYPE& right) { + if (reg.rects && reg.count) { + const int cur_span_top = reg.rects->top; + reg.rects++; + reg.count--; + if (!reg.count || reg.rects->top != cur_span_top) { + left = max_value; + right = max_value; + } else { + left = reg.rects->left + reg.dx; + right = reg.rects->right + reg.dx; + } + } + } + }; + + Spanner spanner; +}; + +// ---------------------------------------------------------------------------- +}; + +#endif /* ANDROID_UI_PRIVATE_REGION_HELPER_H */ diff --git a/include/private/ui/SharedState.h b/include/private/ui/SharedState.h index 546d0ad..646cc10 100644 --- a/include/private/ui/SharedState.h +++ b/include/private/ui/SharedState.h @@ -32,16 +32,12 @@ namespace android { struct surface_info_t { // 4 longs, 16 bytes enum { - eBufferDirty = 0x01 + eBufferDirty = 0x01, + eNeedNewBuffer = 0x02 }; - uint16_t w; - uint16_t h; - uint16_t stride; - uint16_t bpr; - uint16_t reserved; - uint8_t format; + uint8_t reserved[11]; uint8_t flags; - ssize_t bits_offset; + status_t status; }; // --------------------------------------------------------------------------- @@ -110,8 +106,6 @@ struct per_client_cblk_t // 4KB max INSPECT = 0x00000002 }; - per_client_cblk_t(); - // these functions are used by the clients status_t validate(size_t i) const; int32_t lock_layer(size_t i, uint32_t flags); @@ -138,12 +132,9 @@ struct display_cblk_t struct surface_flinger_cblk_t // 4KB max { - surface_flinger_cblk_t(); - uint8_t connected; uint8_t reserved[3]; uint32_t pad[7]; - display_cblk_t displays[NUM_DISPLAY_MAX]; }; diff --git a/include/private/ui/SurfaceBuffer.h b/include/private/ui/SurfaceBuffer.h new file mode 100644 index 0000000..c45abeb --- /dev/null +++ b/include/private/ui/SurfaceBuffer.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UI_PRIVATE_SURFACE_BUFFER_H +#define ANDROID_UI_PRIVATE_SURFACE_BUFFER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/RefBase.h> + +#include <private/ui/android_natives_priv.h> + +namespace android { + +// --------------------------------------------------------------------------- + +class BufferMapper; +class Rect; +class Surface; +class SurfaceBuffer; + +// --------------------------------------------------------------------------- + +class SurfaceBuffer + : public EGLNativeBase< + android_native_buffer_t, + SurfaceBuffer, + LightRefBase<SurfaceBuffer> > +{ +public: + status_t lock(uint32_t usage, void** vaddr); + status_t lock(uint32_t usage, const Rect& rect, void** vaddr); + status_t unlock(); + +protected: + SurfaceBuffer(); + SurfaceBuffer(const Parcel& reply); + virtual ~SurfaceBuffer(); + bool mOwner; + + inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } + inline BufferMapper& getBufferMapper() { return mBufferMapper; } + +private: + friend class Surface; + friend class BpSurface; + friend class BnSurface; + friend class LightRefBase<SurfaceBuffer>; + + SurfaceBuffer& operator = (const SurfaceBuffer& rhs); + const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const; + + static status_t writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer); + + BufferMapper& mBufferMapper; +}; + +}; // namespace android + +#endif // ANDROID_UI_PRIVATE_SURFACE_BUFFER_H + diff --git a/include/private/ui/SurfaceFlingerSynchro.h b/include/private/ui/SurfaceFlingerSynchro.h index ff91b61..7386d33 100644 --- a/include/private/ui/SurfaceFlingerSynchro.h +++ b/include/private/ui/SurfaceFlingerSynchro.h @@ -21,7 +21,6 @@ #include <stdint.h> #include <sys/types.h> #include <utils/Errors.h> -#include <utils/threads.h> #include <ui/ISurfaceComposer.h> namespace android { @@ -31,7 +30,6 @@ class SurfaceFlinger; class SurfaceFlingerSynchro { public: - // client constructor SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger); ~SurfaceFlingerSynchro(); @@ -40,34 +38,8 @@ public: status_t signal(); private: - class Barrier { - public: - Barrier(); - ~Barrier(); - void open(); - void close(); - void waitAndClose(); - status_t waitAndClose(nsecs_t timeout); - private: - enum { OPENED, CLOSED }; - mutable Mutex lock; - mutable Condition cv; - volatile int state; - }; - friend class SurfaceFlinger; - - // server constructor - SurfaceFlingerSynchro(); - - void open(); - - // wait until there is some work to do - status_t wait(); - status_t wait(nsecs_t timeout); - sp<ISurfaceComposer> mSurfaceComposer; - Barrier mBarrier; }; }; // namespace android diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h new file mode 100644 index 0000000..ee843e9 --- /dev/null +++ b/include/private/ui/android_natives_priv.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_ANDROID_NATIVES_PRIV_H +#define ANDROID_ANDROID_NATIVES_PRIV_H + +#include <ui/egl/android_natives.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +struct android_native_buffer_t +{ +#ifdef __cplusplus + android_native_buffer_t() { + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + int width; + int height; + int stride; + int format; + int usage; + + void* reserved[2]; + + buffer_handle_t handle; + + void* reserved_proc[8]; +}; + + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + +/*****************************************************************************/ + +#endif /* ANDROID_ANDROID_NATIVES_PRIV_H */ diff --git a/include/ui/BufferMapper.h b/include/ui/BufferMapper.h new file mode 100644 index 0000000..5f084be --- /dev/null +++ b/include/ui/BufferMapper.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UI_BUFFER_MAPPER_H +#define ANDROID_UI_BUFFER_MAPPER_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Singleton.h> + +#include <hardware/gralloc.h> + + +struct gralloc_module_t; + +namespace android { + +// --------------------------------------------------------------------------- + +class Rect; + +class BufferMapper : public Singleton<BufferMapper> +{ +public: + static inline BufferMapper& get() { return getInstance(); } + + status_t registerBuffer(buffer_handle_t handle); + + status_t unregisterBuffer(buffer_handle_t handle); + + status_t lock(buffer_handle_t handle, + int usage, const Rect& bounds, void** vaddr); + + status_t unlock(buffer_handle_t handle); + + // dumps information about the mapping of this handle + void dump(buffer_handle_t handle); + +private: + friend class Singleton<BufferMapper>; + BufferMapper(); + gralloc_module_t const *mAllocMod; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_UI_BUFFER_MAPPER_H + diff --git a/include/ui/EGLDisplaySurface.h b/include/ui/EGLDisplaySurface.h deleted file mode 100644 index a8b5853..0000000 --- a/include/ui/EGLDisplaySurface.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_EGL_DISPLAY_SURFACE_H -#define ANDROID_EGL_DISPLAY_SURFACE_H - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Timers.h> - -#include <ui/EGLNativeSurface.h> - -#include <pixelflinger/pixelflinger.h> -#include <linux/fb.h> - -#include <EGL/egl.h> - -struct copybit_device_t; -struct copybit_image_t; - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class Region; -class Rect; - -class EGLDisplaySurface : public EGLNativeSurface<EGLDisplaySurface> -{ -public: - EGLDisplaySurface(); - ~EGLDisplaySurface(); - - int32_t getPageFlipCount() const; - void copyFrontToBack(const Region& copyback); - void copyFrontToImage(const copybit_image_t& dst); - void copyBackToImage(const copybit_image_t& dst); - - void setSwapRectangle(int l, int t, int w, int h); - -private: - static void hook_incRef(NativeWindowType window); - static void hook_decRef(NativeWindowType window); - static uint32_t hook_swapBuffers(NativeWindowType window); - - uint32_t swapBuffers(); - - status_t mapFrameBuffer(); - - enum { - PAGE_FLIP = 0x00000001 - }; - GGLSurface mFb[2]; - int mIndex; - uint32_t mFlags; - size_t mSize; - fb_var_screeninfo mInfo; - fb_fix_screeninfo mFinfo; - int32_t mPageFlipCount; - nsecs_t mTime; - int32_t mSwapCount; - nsecs_t mSleep; - uint32_t mFeatureFlags; - copybit_device_t* mBlitEngine; -}; - -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_EGL_DISPLAY_SURFACE_H - diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h deleted file mode 100644 index 3494234..0000000 --- a/include/ui/EGLNativeWindowSurface.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_EGL_NATIVE_WINDOW_SURFACE_H -#define ANDROID_EGL_NATIVE_WINDOW_SURFACE_H - -#include <stdint.h> -#include <sys/types.h> -#include <ui/EGLNativeSurface.h> -#include <EGL/egl.h> - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class Surface; - -class EGLNativeWindowSurface : public EGLNativeSurface<EGLNativeWindowSurface> -{ -public: - EGLNativeWindowSurface(const sp<Surface>& surface); - ~EGLNativeWindowSurface(); - - void setSwapRectangle(int l, int t, int w, int h); - -private: - static void hook_incRef(NativeWindowType window); - static void hook_decRef(NativeWindowType window); - static uint32_t hook_swapBuffers(NativeWindowType window); - static void hook_connect(NativeWindowType window); - static void hook_disconnect(NativeWindowType window); - - uint32_t swapBuffers(); - void connect(); - void disconnect(); - - sp<Surface> mSurface; - bool mConnected; -}; - -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_EGL_NATIVE_WINDOW_SURFACE_H - diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h new file mode 100644 index 0000000..a780472 --- /dev/null +++ b/include/ui/FramebufferNativeWindow.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H +#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H + +#include <stdint.h> +#include <sys/types.h> + +#include <EGL/egl.h> + +#include <utils/threads.h> +#include <ui/Rect.h> + +#include <pixelflinger/pixelflinger.h> + +#include <ui/egl/android_natives.h> + + +extern "C" EGLNativeWindowType android_createDisplaySurface(void); + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class Surface; +class NativeBuffer; + +// --------------------------------------------------------------------------- + +class FramebufferNativeWindow + : public EGLNativeBase< + android_native_window_t, + FramebufferNativeWindow, + LightRefBase<FramebufferNativeWindow> > +{ +public: + FramebufferNativeWindow(); + + framebuffer_device_t const * getDevice() const { return fbDev; } + + bool isUpdateOnDemand() const { return mUpdateOnDemand; } + status_t setUpdateRectangle(const Rect& updateRect); + +private: + friend class LightRefBase<FramebufferNativeWindow>; + ~FramebufferNativeWindow(); // this class cannot be overloaded + static int setSwapInterval(android_native_window_t* window, int interval); + static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); + static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + + framebuffer_device_t* fbDev; + alloc_device_t* grDev; + + sp<NativeBuffer> buffers[2]; + sp<NativeBuffer> front; + + mutable Mutex mutex; + Condition mCondition; + int32_t mNumBuffers; + int32_t mNumFreeBuffers; + int32_t mBufferHead; + bool mUpdateOnDemand; +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H + diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 136e801..adba45a 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -26,6 +26,7 @@ #include <ui/PixelFormat.h> #include <hardware/hardware.h> +#include <hardware/gralloc.h> namespace android { @@ -33,6 +34,7 @@ typedef int32_t SurfaceID; class IMemoryHeap; class OverlayRef; +class SurfaceBuffer; class ISurface : public IInterface { @@ -42,11 +44,13 @@ protected: UNREGISTER_BUFFERS, POST_BUFFER, // one-way transaction CREATE_OVERLAY, + GET_BUFFER, }; public: DECLARE_META_INTERFACE(Surface); + virtual sp<SurfaceBuffer> getBuffer() = 0; class BufferHeap { public: @@ -78,9 +82,7 @@ public: }; virtual status_t registerBuffers(const BufferHeap& buffers) = 0; - virtual void postBuffer(ssize_t offset) = 0; // one-way - virtual void unregisterBuffers() = 0; virtual sp<OverlayRef> createOverlay( diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h index 5b062a8..ab6dd56 100644 --- a/include/ui/ISurfaceComposer.h +++ b/include/ui/ISurfaceComposer.h @@ -32,7 +32,6 @@ namespace android { // ---------------------------------------------------------------------------- class DisplayInfo; -class IGPUCallback; class ISurfaceComposer : public IInterface { @@ -112,37 +111,12 @@ public: */ virtual void bootFinished() = 0; - /* get access to the GPU. Access is relinquished when releasing regs */ - struct gpu_info_t { - struct gpu_region_t { - sp<IMemory> region; - size_t reserved; - }; - sp<IMemory> regs; - size_t count; - gpu_region_t regions[2]; - }; - virtual status_t requestGPU( - const sp<IGPUCallback>& callback, - gpu_info_t* gpu) = 0; - - /* take the gpu back from any apps using it. They'll get a - * EGL_CONTEXT_LOST error */ - virtual status_t revokeGPU() = 0; - /* Signal surfaceflinger that there might be some work to do * This is an ASYNCHRONOUS call. */ virtual void signal() const = 0; }; -class IGPUCallback : public IInterface -{ -public: - DECLARE_META_INTERFACE(GPUCallback); - virtual void gpuLost() = 0; //one-way -}; - // ---------------------------------------------------------------------------- class BnSurfaceComposer : public BnInterface<ISurfaceComposer> @@ -159,8 +133,6 @@ public: SET_ORIENTATION, FREEZE_DISPLAY, UNFREEZE_DISPLAY, - REQUEST_GPU, - REVOKE_GPU, SIGNAL }; @@ -170,15 +142,6 @@ public: uint32_t flags = 0); }; -class BnGPUCallback : public BnInterface<IGPUCallback> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h index b6cbb0b..e93a4fa 100644 --- a/include/ui/ISurfaceFlingerClient.h +++ b/include/ui/ISurfaceFlingerClient.h @@ -52,7 +52,6 @@ public: struct surface_data_t { int32_t token; int32_t identity; - sp<IMemoryHeap> heap[2]; status_t readFromParcel(const Parcel& parcel); status_t writeToParcel(Parcel* parcel) const; }; diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h index 14af823..6d87321 100644 --- a/include/ui/PixelFormat.h +++ b/include/ui/PixelFormat.h @@ -84,6 +84,13 @@ typedef int32_t PixelFormat; struct PixelFormatInfo { + enum { + INDEX_ALPHA = 0, + INDEX_RED = 1, + INDEX_GREEN = 2, + INDEX_BLUE = 3 + }; + enum { // components ALPHA = 1, RGB = 2, @@ -95,20 +102,33 @@ struct PixelFormatInfo Y_CB_CR_I = 8, }; + struct szinfo { + uint8_t h; + uint8_t l; + }; + inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { } size_t getScanlineSize(unsigned int width) const; + size_t getSize(size_t ci) const { + return (ci <= 3) ? (cinfo[ci].h - cinfo[ci].l) : 0; + } size_t version; PixelFormat format; size_t bytesPerPixel; size_t bitsPerPixel; - uint8_t h_alpha; - uint8_t l_alpha; - uint8_t h_red; - uint8_t l_red; - uint8_t h_green; - uint8_t l_green; - uint8_t h_blue; - uint8_t l_blue; + union { + szinfo cinfo[4]; + struct { + uint8_t h_alpha; + uint8_t l_alpha; + uint8_t h_red; + uint8_t l_red; + uint8_t h_green; + uint8_t l_green; + uint8_t h_blue; + uint8_t l_blue; + }; + }; uint8_t components; uint8_t reserved0[3]; uint32_t reserved1; diff --git a/include/ui/Rect.h b/include/ui/Rect.h index da72944..a213c09 100644 --- a/include/ui/Rect.h +++ b/include/ui/Rect.h @@ -30,6 +30,8 @@ public: int right; int bottom; + typedef int value_type; + // we don't provide copy-ctor and operator= on purpose // because we want the compiler generated versions @@ -46,7 +48,11 @@ public: } void makeInvalid(); - + + inline void clear() { + left = top = right = bottom = 0; + } + // a valid rectangle has a non negative width and height inline bool isValid() const { return (width()>=0) && (height()>=0); diff --git a/include/ui/Region.h b/include/ui/Region.h index 68cb52e..4299ea5 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -27,8 +27,6 @@ #include <hardware/copybit.h> -#include <core/SkRegion.h> - namespace android { // --------------------------------------------------------------------------- @@ -40,7 +38,6 @@ class Region public: Region(); Region(const Region& rhs); - explicit Region(const SkRegion& rhs); explicit Region(const Rect& rhs); explicit Region(const Parcel& parcel); explicit Region(const void* buffer); @@ -48,65 +45,75 @@ public: Region& operator = (const Region& rhs); - inline bool isEmpty() const { return mRegion.isEmpty(); } - inline bool isRect() const { return mRegion.isRect(); } - - Rect bounds() const; + inline bool isEmpty() const { return mBounds.isEmpty(); } + inline bool isRect() const { return mStorage.isEmpty(); } - const SkRegion& toSkRegion() const; + inline const Rect& getBounds() const { return mBounds; } + inline const Rect& bounds() const { return getBounds(); } void clear(); void set(const Rect& r); + void set(uint32_t w, uint32_t h); Region& orSelf(const Rect& rhs); Region& andSelf(const Rect& rhs); + Region& subtractSelf(const Rect& rhs); // boolean operators, applied on this Region& orSelf(const Region& rhs); Region& andSelf(const Region& rhs); Region& subtractSelf(const Region& rhs); + // boolean operators + const Region merge(const Rect& rhs) const; + const Region intersect(const Rect& rhs) const; + const Region subtract(const Rect& rhs) const; + + // boolean operators + const Region merge(const Region& rhs) const; + const Region intersect(const Region& rhs) const; + const Region subtract(const Region& rhs) const; + // these translate rhs first Region& translateSelf(int dx, int dy); Region& orSelf(const Region& rhs, int dx, int dy); Region& andSelf(const Region& rhs, int dx, int dy); Region& subtractSelf(const Region& rhs, int dx, int dy); - // boolean operators - Region merge(const Region& rhs) const; - Region intersect(const Region& rhs) const; - Region subtract(const Region& rhs) const; - // these translate rhs first - Region translate(int dx, int dy) const; - Region merge(const Region& rhs, int dx, int dy) const; - Region intersect(const Region& rhs, int dx, int dy) const; - Region subtract(const Region& rhs, int dx, int dy) const; + const Region translate(int dx, int dy) const; + const Region merge(const Region& rhs, int dx, int dy) const; + const Region intersect(const Region& rhs, int dx, int dy) const; + const Region subtract(const Region& rhs, int dx, int dy) const; // convenience operators overloads - inline Region operator | (const Region& rhs) const; - inline Region operator & (const Region& rhs) const; - inline Region operator - (const Region& rhs) const; - inline Region operator + (const Point& pt) const; + inline const Region operator | (const Region& rhs) const; + inline const Region operator & (const Region& rhs) const; + inline const Region operator - (const Region& rhs) const; + inline const Region operator + (const Point& pt) const; inline Region& operator |= (const Region& rhs); inline Region& operator &= (const Region& rhs); inline Region& operator -= (const Region& rhs); inline Region& operator += (const Point& pt); - class iterator { - SkRegion::Iterator mIt; - public: - iterator(const Region& r); - inline operator bool () const { return !done(); } - int iterate(Rect* rect); - private: - inline bool done() const { - return const_cast<SkRegion::Iterator&>(mIt).done(); - } - }; + + /* various ways to access the rectangle list */ + + typedef Rect const* const_iterator; + + const_iterator begin() const; + const_iterator end() const; - size_t rects(Vector<Rect>& rectList) const; + /* no user serviceable parts here... */ + + size_t getRects(Vector<Rect>& rectList) const; + Rect const* getArray(size_t* count) const; + + + // add a rectangle to the internal list. This rectangle must + // be sorted in Y and X and must not make the region invalid. + void addRectUnchecked(int l, int t, int r, int b); // flatten/unflatten a region to/from a Parcel status_t write(Parcel& parcel) const; @@ -123,20 +130,46 @@ public: void dump(const char* what, uint32_t flags=0) const; private: - SkRegion mRegion; + class rasterizer; + friend class rasterizer; + + Region& operationSelf(const Rect& r, int op); + Region& operationSelf(const Region& r, int op); + Region& operationSelf(const Region& r, int dx, int dy, int op); + const Region operation(const Rect& rhs, int op) const; + const Region operation(const Region& rhs, int op) const; + const Region operation(const Region& rhs, int dx, int dy, int op) const; + + static void boolean_operation(int op, Region& dst, + const Region& lhs, const Region& rhs, int dx, int dy); + static void boolean_operation(int op, Region& dst, + const Region& lhs, const Rect& rhs, int dx, int dy); + + static void boolean_operation(int op, Region& dst, + const Region& lhs, const Region& rhs); + static void boolean_operation(int op, Region& dst, + const Region& lhs, const Rect& rhs); + + static void translate(Region& reg, int dx, int dy); + static void translate(Region& dst, const Region& reg, int dx, int dy); + + static bool validate(const Region& reg, const char* name); + + Rect mBounds; + Vector<Rect> mStorage; }; -Region Region::operator | (const Region& rhs) const { +const Region Region::operator | (const Region& rhs) const { return merge(rhs); } -Region Region::operator & (const Region& rhs) const { +const Region Region::operator & (const Region& rhs) const { return intersect(rhs); } -Region Region::operator - (const Region& rhs) const { +const Region Region::operator - (const Region& rhs) const { return subtract(rhs); } -Region Region::operator + (const Point& pt) const { +const Region Region::operator + (const Point& pt) const { return translate(pt.x, pt.y); } @@ -157,16 +190,23 @@ Region& Region::operator += (const Point& pt) { // --------------------------------------------------------------------------- struct region_iterator : public copybit_region_t { - region_iterator(const Region& region) : i(region) { + region_iterator(const Region& region) + : b(region.begin()), e(region.end()) { this->next = iterate; } private: static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { - return static_cast<const region_iterator*>(self) - ->i.iterate(reinterpret_cast<Rect*>(rect)); + region_iterator const* me = static_cast<region_iterator const*>(self); + if (me->b != me->e) { + *reinterpret_cast<Rect*>(rect) = *me->b++; + return 1; + } + return 0; } - mutable Region::iterator i; + mutable Region::const_iterator b; + Region::const_iterator const e; }; + // --------------------------------------------------------------------------- }; // namespace android diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 33953a9..8c4f63d 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -28,48 +28,40 @@ #include <ui/Region.h> #include <ui/ISurfaceFlingerClient.h> +#include <ui/egl/android_natives.h> + namespace android { // --------------------------------------------------------------------------- +class BufferMapper; class Rect; +class Surface; class SurfaceComposerClient; +struct per_client_cblk_t; +struct layer_cblk_t; -class Surface : public RefBase -{ +// --------------------------------------------------------------------------- +class SurfaceControl : public RefBase +{ public: - struct SurfaceInfo { - uint32_t w; - uint32_t h; - uint32_t bpr; - PixelFormat format; - void* bits; - void* base; - uint32_t reserved[2]; - }; - - bool isValid() const { return this && mToken>=0 && mClient!=0; } + static bool isValid(const sp<SurfaceControl>& surface) { + return (surface != 0) && surface->isValid(); + } + bool isValid() { + return mToken>=0 && mClient!=0; + } + static bool isSameSurface( + const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs); + SurfaceID ID() const { return mToken; } - - status_t lock(SurfaceInfo* info, bool blocking = true); - status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); - status_t unlockAndPost(); - status_t unlock(); - - void* heapBase(int i) const; uint32_t getFlags() const { return mFlags; } + uint32_t getIdentity() const { return mIdentity; } - // setSwapRectangle() is mainly used by EGL - void setSwapRectangle(const Rect& r); - const Rect& swapRectangle() const; - status_t nextBuffer(SurfaceInfo* info); - - sp<Surface> dup() const; - static sp<Surface> readFromParcel(Parcel* parcel); - static status_t writeToParcel(const sp<Surface>& surface, Parcel* parcel); - static bool isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs); - + // release surface data from java + void clear(); + status_t setLayer(int32_t layer); status_t setPosition(int32_t x, int32_t y); status_t setSize(uint32_t w, uint32_t h); @@ -83,8 +75,17 @@ public: status_t setMatrix(float dsdx, float dtdx, float dsdy, float dtdy); status_t setFreezeTint(uint32_t tint); - uint32_t getIdentity() const { return mIdentity; } + static status_t writeSurfaceToParcel( + const sp<SurfaceControl>& control, Parcel* parcel); + + sp<Surface> getSurface() const; + private: + // can't be copied + SurfaceControl& operator = (SurfaceControl& rhs); + SurfaceControl(const SurfaceControl& rhs); + + friend class SurfaceComposerClient; // camera and camcorder need access to the ISurface binder interface for preview @@ -92,43 +93,130 @@ private: friend class MediaRecorder; // mediaplayer needs access to ISurface for display friend class MediaPlayer; + // for testing friend class Test; const sp<ISurface>& getISurface() const { return mSurface; } + - // can't be copied - Surface& operator = (Surface& rhs); - Surface(const Surface& rhs); + friend class Surface; - Surface(const sp<SurfaceComposerClient>& client, + SurfaceControl( + const sp<SurfaceComposerClient>& client, const sp<ISurface>& surface, const ISurfaceFlingerClient::surface_data_t& data, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - bool owner = true); + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + + ~SurfaceControl(); + + status_t validate(per_client_cblk_t const* cblk) const; + void destroy(); + + sp<SurfaceComposerClient> mClient; + sp<ISurface> mSurface; + SurfaceID mToken; + uint32_t mIdentity; + PixelFormat mFormat; + uint32_t mFlags; + mutable Mutex mLock; + + mutable sp<Surface> mSurfaceData; +}; + +// --------------------------------------------------------------------------- + +class Surface + : public EGLNativeBase<android_native_window_t, Surface, RefBase> +{ +public: + struct SurfaceInfo { + uint32_t w; + uint32_t h; + uint32_t s; + uint32_t usage; + PixelFormat format; + void* bits; + uint32_t reserved[2]; + }; + + Surface(const Parcel& data); + + static bool isValid(const sp<Surface>& surface) { + return (surface != 0) && surface->isValid(); + } + bool isValid() { + return mToken>=0 && mClient!=0; + } + static bool isSameSurface( + const sp<Surface>& lhs, const sp<Surface>& rhs); + SurfaceID ID() const { return mToken; } + uint32_t getFlags() const { return mFlags; } + uint32_t getIdentity() const { return mIdentity; } - Surface(Surface const* rhs); - ~Surface(); + status_t lock(SurfaceInfo* info, bool blocking = true); + status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); + status_t unlockAndPost(); + + // setSwapRectangle() is intended to be used by GL ES clients + void setSwapRectangle(const Rect& r); + +private: + // can't be copied + Surface& operator = (Surface& rhs); + Surface(const Surface& rhs); - Region dirtyRegion() const; - void setDirtyRegion(const Region& region) const; + Surface(const sp<SurfaceControl>& control); + void init(); + ~Surface(); + + friend class SurfaceComposerClient; + friend class SurfaceControl; - // this locks protects calls to lockSurface() / unlockSurface() - // and is called by SurfaceComposerClient. - Mutex& getLock() const { return mSurfaceLock; } + // camera and camcorder need access to the ISurface binder interface for preview + friend class Camera; + friend class MediaRecorder; + // mediaplayer needs access to ISurface for display + friend class MediaPlayer; + friend class Test; + const sp<ISurface>& getISurface() const { return mSurface; } + status_t getBufferLocked(int index); + + status_t validate(per_client_cblk_t const* cblk) const; + static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); + + inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } + inline BufferMapper& getBufferMapper() { return mBufferMapper; } + + static int setSwapInterval(android_native_window_t* window, int interval); + static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); + static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + + int dequeueBuffer(android_native_buffer_t** buffer); + int lockBuffer(android_native_buffer_t* buffer); + int queueBuffer(android_native_buffer_t* buffer); + + status_t dequeueBuffer(sp<SurfaceBuffer>* buffer); + status_t lockBuffer(const sp<SurfaceBuffer>& buffer); + status_t queueBuffer(const sp<SurfaceBuffer>& buffer); + + + alloc_device_t* mAllocDevice; sp<SurfaceComposerClient> mClient; sp<ISurface> mSurface; - sp<IMemoryHeap> mHeap[2]; + sp<SurfaceBuffer> mBuffers[2]; + sp<SurfaceBuffer> mLockedBuffer; SurfaceID mToken; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; - const bool mOwner; - mutable void* mSurfaceHeapBase[2]; mutable Region mDirtyRegion; - mutable Rect mSwapRectangle; + mutable Region mOldDirtyRegion; mutable uint8_t mBackbufferIndex; mutable Mutex mSurfaceLock; + Rect mSwapRectangle; + BufferMapper& mBufferMapper; }; }; // namespace android diff --git a/include/ui/SurfaceComposerClient.h b/include/ui/SurfaceComposerClient.h index 76a3b55..2a35256 100644 --- a/include/ui/SurfaceComposerClient.h +++ b/include/ui/SurfaceComposerClient.h @@ -62,7 +62,7 @@ public: // surface creation / destruction //! Create a surface - sp<Surface> createSurface( + sp<SurfaceControl> createSurface( int pid, //!< pid of the process the surfacec is for DisplayID display, //!< Display to create this surface on uint32_t w, //!< width in pixel @@ -111,51 +111,35 @@ public: private: friend class Surface; + friend class SurfaceControl; SurfaceComposerClient(const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn); - status_t hide(Surface* surface); - status_t show(Surface* surface, int32_t layer = -1); - status_t freeze(Surface* surface); - status_t unfreeze(Surface* surface); - status_t setFlags(Surface* surface, uint32_t flags, uint32_t mask); - status_t setTransparentRegionHint(Surface* surface, const Region& transparent); - status_t setLayer(Surface* surface, int32_t layer); - status_t setAlpha(Surface* surface, float alpha=1.0f); - status_t setFreezeTint(Surface* surface, uint32_t tint); - status_t setMatrix(Surface* surface, float dsdx, float dtdx, float dsdy, float dtdy); - status_t setPosition(Surface* surface, int32_t x, int32_t y); - status_t setSize(Surface* surface, uint32_t w, uint32_t h); + status_t hide(SurfaceID id); + status_t show(SurfaceID id, int32_t layer = -1); + status_t freeze(SurfaceID id); + status_t unfreeze(SurfaceID id); + status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask); + status_t setTransparentRegionHint(SurfaceID id, const Region& transparent); + status_t setLayer(SurfaceID id, int32_t layer); + status_t setAlpha(SurfaceID id, float alpha=1.0f); + status_t setFreezeTint(SurfaceID id, uint32_t tint); + status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); + status_t setPosition(SurfaceID id, int32_t x, int32_t y); + status_t setSize(SurfaceID id, uint32_t w, uint32_t h); - //! Unlock the surface, and specify the dirty region if any - status_t unlockAndPostSurface(Surface* surface); - status_t unlockSurface(Surface* surface); - - status_t lockSurface(Surface* surface, - Surface::SurfaceInfo* info, - Region* dirty, - bool blocking = true); - - status_t nextBuffer(Surface* surface, - Surface::SurfaceInfo* info); + void signalServer(); status_t destroySurface(SurfaceID sid); void _init(const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn); - void _signal_server(); - static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); - inline layer_state_t* _get_state_l(const sp<Surface>& surface); - layer_state_t* _lockLayerState(const sp<Surface>& surface); + inline layer_state_t* _get_state_l(SurfaceID id); + layer_state_t* _lockLayerState(SurfaceID id); inline void _unlockLayerState(); - status_t validateSurface( - per_client_cblk_t const* cblk, Surface const * surface); - - void pinHeap(const sp<IMemoryHeap>& heap); - mutable Mutex mLock; layer_state_t* mPrebuiltLayerState; SortedVector<layer_state_t> mStates; @@ -167,9 +151,6 @@ private: per_client_cblk_t* mControl; sp<IMemory> mControlMemory; sp<ISurfaceFlingerClient> mClient; - sp<IMemoryHeap> mSurfaceHeap; - uint8_t* mSurfaceHeapBase; - void* mGL; SurfaceFlingerSynchro* mSignalServer; }; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h new file mode 100644 index 0000000..0398ea7 --- /dev/null +++ b/include/ui/egl/android_natives.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_ANDROID_NATIVES_H +#define ANDROID_ANDROID_NATIVES_H + +#include <sys/types.h> +#include <string.h> + +#include <hardware/gralloc.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \ + (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d)) + +#define ANDROID_NATIVE_WINDOW_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d') + +#define ANDROID_NATIVE_BUFFER_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r') + +// --------------------------------------------------------------------------- + +struct android_native_buffer_t; + +// --------------------------------------------------------------------------- + +struct android_native_base_t +{ + /* a magic value defined by the actual EGL native type */ + int magic; + + /* the sizeof() of the actual EGL native type */ + int version; + + void* reserved[4]; + + /* reference-counting interface */ + void (*incRef)(struct android_native_base_t* base); + void (*decRef)(struct android_native_base_t* base); +}; + +// --------------------------------------------------------------------------- + +struct android_native_window_t +{ +#ifdef __cplusplus + android_native_window_t() + : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) + { + common.magic = ANDROID_NATIVE_WINDOW_MAGIC; + common.version = sizeof(android_native_window_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + /* flags describing some attributes of this surface or its updater */ + const uint32_t flags; + + /* min swap interval supported by this updated */ + const int minSwapInterval; + + /* max swap interval supported by this updated */ + const int maxSwapInterval; + + /* horizontal and vertical resolution in DPI */ + const float xdpi; + const float ydpi; + + /* Some storage reserved for the OEM's driver. */ + intptr_t oem[4]; + + + /* + * Set the swap interval for this surface. + * + * Returns 0 on success or -errno on error. + */ + int (*setSwapInterval)(struct android_native_window_t* window, + int interval); + + /* + * hook called by EGL to acquire a buffer. After this call, the buffer + * is not locked, so its content cannot be modified. + * this call may block if no buffers are available. + * + * Returns 0 on success or -errno on error. + */ + int (*dequeueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t** buffer); + + /* + * hook called by EGL to lock a buffer. This MUST be called before modifying + * the content of a buffer. The buffer must have been acquired with + * dequeueBuffer first. + * + * Returns 0 on success or -errno on error. + */ + int (*lockBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + /* + * hook called by EGL when modifications to the render buffer are done. + * This unlocks and post the buffer. + * + * Buffers MUST be queued in the same order than they were dequeued. + * + * Returns 0 on success or -errno on error. + */ + int (*queueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + + + void* reserved_proc[5]; +}; + +// --------------------------------------------------------------------------- + +/* FIXME: this is legacy for pixmaps */ +struct egl_native_pixmap_t +{ + int32_t version; /* must be 32 */ + int32_t width; + int32_t height; + int32_t stride; + uint8_t* data; + uint8_t format; + uint8_t rfu[3]; + union { + uint32_t compressedFormat; + int32_t vstride; + }; + int32_t reserved; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +/*****************************************************************************/ + +#ifdef __cplusplus + +#include <utils/RefBase.h> + +namespace android { + +/* + * This helper class turns an EGL android_native_xxx type into a C++ + * reference-counted object; with proper type conversions. + */ +template <typename NATIVE_TYPE, typename TYPE, typename REF> +class EGLNativeBase : public NATIVE_TYPE, public REF +{ +protected: + typedef EGLNativeBase<NATIVE_TYPE, TYPE, REF> BASE; + EGLNativeBase() : NATIVE_TYPE(), REF() { + NATIVE_TYPE::common.incRef = incRef; + NATIVE_TYPE::common.decRef = decRef; + } + static inline TYPE* getSelf(NATIVE_TYPE* self) { + return static_cast<TYPE*>(self); + } + static inline TYPE const* getSelf(NATIVE_TYPE const* self) { + return static_cast<TYPE const *>(self); + } + static inline TYPE* getSelf(android_native_base_t* base) { + return getSelf(reinterpret_cast<NATIVE_TYPE*>(base)); + } + static inline TYPE const * getSelf(android_native_base_t const* base) { + return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base)); + } + static void incRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->incStrong(self); + } + static void decRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->decStrong(self); + } +}; + +} // namespace android +#endif // __cplusplus + +/*****************************************************************************/ + +#endif /* ANDROID_ANDROID_NATIVES_H */ diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h index f4513ee..6bcdea4 100644 --- a/include/utils/KeyedVector.h +++ b/include/utils/KeyedVector.h @@ -164,7 +164,7 @@ ssize_t KeyedVector<KEY,VALUE>::replaceValueFor(const KEY& key, const VALUE& val template<typename KEY, typename VALUE> inline ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) { if (index<size()) { - mVector.editValueAt(index).value = item; + mVector.editItemAt(index).value = item; return index; } return BAD_INDEX; diff --git a/include/utils/List.h b/include/utils/List.h index 1a6be9a..4041a89 100644 --- a/include/utils/List.h +++ b/include/utils/List.h @@ -22,147 +22,200 @@ // construction, so if the compiler's auto-generated versions won't work for // you, define your own. // -// The only class you want to use from here is "List". Do not use classes -// starting with "_" directly. +// The only class you want to use from here is "List". // #ifndef _LIBS_UTILS_LIST_H #define _LIBS_UTILS_LIST_H -namespace android { - -/* - * One element in the list. - */ -template<class T> class _ListNode { -public: - typedef _ListNode<T> _Node; - - _ListNode(const T& val) : mVal(val) {} - ~_ListNode(void) {} - - T& getRef(void) { return mVal; } - void setVal(const T& val) { mVal = val; } +#include <stddef.h> +#include <stdint.h> - _Node* getPrev(void) const { return mpPrev; } - void setPrev(_Node* ptr) { mpPrev = ptr; } - _Node* getNext(void) const { return mpNext; } - void setNext(_Node* ptr) { mpNext = ptr; } - -private: - T mVal; - _Node* mpPrev; - _Node* mpNext; -}; +namespace android { /* - * Iterator for walking through the list. + * Doubly-linked list. Instantiate with "List<MyClass> myList". + * + * Objects added to the list are copied using the assignment operator, + * so this must be defined. */ -template<class T, class Tref> class _ListIterator { -public: - typedef _ListIterator<T,Tref> _Iter; - typedef _ListNode<T> _Node; - - _ListIterator(void) {} - _ListIterator(_Node* ptr) : mpNode(ptr) {} - ~_ListIterator(void) {} - - /* - * Dereference operator. Used to get at the juicy insides. - */ - Tref operator*() const { return mpNode->getRef(); } - +template<typename T> +class List +{ +protected: /* - * Iterator comparison. + * One element in the list. */ - bool operator==(const _Iter& right) const { return mpNode == right.mpNode; } - bool operator!=(const _Iter& right) const { return mpNode != right.mpNode; } + class _Node { + public: + explicit _Node(const T& val) : mVal(val) {} + ~_Node() {} + inline T& getRef() { return mVal; } + inline const T& getRef() const { return mVal; } + inline _Node* getPrev() const { return mpPrev; } + inline _Node* getNext() const { return mpNext; } + inline void setVal(const T& val) { mVal = val; } + inline void setPrev(_Node* ptr) { mpPrev = ptr; } + inline void setNext(_Node* ptr) { mpNext = ptr; } + private: + friend class List; + friend class _ListIterator; + T mVal; + _Node* mpPrev; + _Node* mpNext; + }; /* - * Incr/decr, used to move through the list. + * Iterator for walking through the list. */ - _Iter& operator++(void) { // pre-increment - mpNode = mpNode->getNext(); - return *this; - } - _Iter operator++(int) { // post-increment - _Iter tmp = *this; - ++*this; - return tmp; - } - _Iter& operator--(void) { // pre-increment - mpNode = mpNode->getPrev(); - return *this; - } - _Iter operator--(int) { // post-increment - _Iter tmp = *this; - --*this; - return tmp; - } + + template <typename TYPE> + struct CONST_ITERATOR { + typedef _Node const * NodePtr; + typedef const TYPE Type; + }; + + template <typename TYPE> + struct NON_CONST_ITERATOR { + typedef _Node* NodePtr; + typedef TYPE Type; + }; + + template< + typename U, + template <class> class Constness + > + class _ListIterator { + typedef _ListIterator<U, Constness> _Iter; + typedef typename Constness<U>::NodePtr _NodePtr; + typedef typename Constness<U>::Type _Type; + + explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {} + + public: + _ListIterator() {} + _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {} + ~_ListIterator() {} + + // this will handle conversions from iterator to const_iterator + // (and also all convertible iterators) + // Here, in this implementation, the iterators can be converted + // if the nodes can be converted + template<typename V> explicit + _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {} + + + /* + * Dereference operator. Used to get at the juicy insides. + */ + _Type& operator*() const { return mpNode->getRef(); } + _Type* operator->() const { return &(mpNode->getRef()); } + + /* + * Iterator comparison. + */ + inline bool operator==(const _Iter& right) const { + return mpNode == right.mpNode; } + + inline bool operator!=(const _Iter& right) const { + return mpNode != right.mpNode; } + + /* + * handle comparisons between iterator and const_iterator + */ + template<typename OTHER> + inline bool operator==(const OTHER& right) const { + return mpNode == right.mpNode; } + + template<typename OTHER> + inline bool operator!=(const OTHER& right) const { + return mpNode != right.mpNode; } + + /* + * Incr/decr, used to move through the list. + */ + inline _Iter& operator++() { // pre-increment + mpNode = mpNode->getNext(); + return *this; + } + const _Iter operator++(int) { // post-increment + _Iter tmp(*this); + mpNode = mpNode->getNext(); + return tmp; + } + inline _Iter& operator--() { // pre-increment + mpNode = mpNode->getPrev(); + return *this; + } + const _Iter operator--(int) { // post-increment + _Iter tmp(*this); + mpNode = mpNode->getPrev(); + return tmp; + } - _Node* getNode(void) const { return mpNode; } + inline _NodePtr getNode() const { return mpNode; } -private: - _Node* mpNode; -}; + private: + friend class List; + _NodePtr mpNode; + }; - -/* - * Doubly-linked list. Instantiate with "List<MyClass> myList". - * - * Objects added to the list are copied using the assignment operator, - * so this must be defined. - */ -template<class T> class List { public: - typedef _ListNode<T> _Node; - - List(void) { + List() { prep(); } List(const List<T>& src) { // copy-constructor prep(); insert(begin(), src.begin(), src.end()); } - virtual ~List(void) { + virtual ~List() { clear(); delete[] (unsigned char*) mpMiddle; } - typedef _ListIterator<T,T&> iterator; - typedef _ListIterator<T, const T&> const_iterator; + typedef _ListIterator<T, NON_CONST_ITERATOR> iterator; + typedef _ListIterator<T, CONST_ITERATOR> const_iterator; List<T>& operator=(const List<T>& right); /* returns true if the list is empty */ - bool empty(void) const { return mpMiddle->getNext() == mpMiddle; } + inline bool empty() const { return mpMiddle->getNext() == mpMiddle; } /* return #of elements in list */ - unsigned int size(void) const { - return distance(begin(), end()); + size_t size() const { + return size_t(distance(begin(), end())); } /* * Return the first element or one past the last element. The - * _ListNode* we're returning is converted to an "iterator" by a + * _Node* we're returning is converted to an "iterator" by a * constructor in _ListIterator. */ - iterator begin() { return mpMiddle->getNext(); } - const_iterator begin() const { return mpMiddle->getNext(); } - iterator end() { return mpMiddle; } - const_iterator end() const { return mpMiddle; } + inline iterator begin() { + return iterator(mpMiddle->getNext()); + } + inline const_iterator begin() const { + return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); + } + inline iterator end() { + return iterator(mpMiddle); + } + inline const_iterator end() const { + return const_iterator(const_cast<_Node const*>(mpMiddle)); + } /* add the object to the head or tail of the list */ void push_front(const T& val) { insert(begin(), val); } void push_back(const T& val) { insert(end(), val); } /* insert before the current node; returns iterator at new node */ - iterator insert(iterator posn, const T& val) { + iterator insert(iterator posn, const T& val) + { _Node* newNode = new _Node(val); // alloc & copy-construct newNode->setNext(posn.getNode()); newNode->setPrev(posn.getNode()->getPrev()); posn.getNode()->getPrev()->setNext(newNode); posn.getNode()->setPrev(newNode); - return newNode; + return iterator(newNode); } /* insert a range of elements before the current node */ @@ -178,18 +231,18 @@ public: pPrev->setNext(pNext); pNext->setPrev(pPrev); delete posn.getNode(); - return pNext; + return iterator(pNext); } /* remove a range of elements */ iterator erase(iterator first, iterator last) { while (first != last) erase(first++); // don't erase than incr later! - return last; + return iterator(last); } /* remove all contents of the list */ - void clear(void) { + void clear() { _Node* pCurrent = mpMiddle->getNext(); _Node* pNext; @@ -207,21 +260,20 @@ public: * will be equal to "last". The iterators must refer to the same * list. * - * (This is actually a generic iterator function. It should be part - * of some other class, possibly an iterator base class. It needs to - * know the difference between a list, which has to march through, - * and a vector, which can just do pointer math.) + * FIXME: This is actually a generic iterator function. It should be a + * template function at the top-level with specializations for things like + * vector<>, which can just do pointer math). Here we limit it to + * _ListIterator of the same type but different constness. */ - unsigned int distance(iterator first, iterator last) { - unsigned int count = 0; - while (first != last) { - ++first; - ++count; - } - return count; - } - unsigned int distance(const_iterator first, const_iterator last) const { - unsigned int count = 0; + template< + typename U, + template <class> class CL, + template <class> class CR + > + ptrdiff_t distance( + _ListIterator<U, CL> first, _ListIterator<U, CR> last) const + { + ptrdiff_t count = 0; while (first != last) { ++first; ++count; @@ -231,12 +283,12 @@ public: private: /* - * I want a _ListNode but don't need it to hold valid data. More + * I want a _Node but don't need it to hold valid data. More * to the point, I don't want T's constructor to fire, since it * might have side-effects or require arguments. So, we do this * slightly uncouth storage alloc. */ - void prep(void) { + void prep() { mpMiddle = (_Node*) new unsigned char[sizeof(_Node)]; mpMiddle->setPrev(mpMiddle); mpMiddle->setNext(mpMiddle); diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index cbda0fd..bd7f28c 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -156,6 +156,10 @@ public: delete static_cast<const T*>(this); } } + //! DEBUGGING ONLY: Get current strong ref count. + inline int32_t getStrongCount() const { + return mCount; + } protected: inline ~LightRefBase() { } diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h new file mode 100644 index 0000000..bc7626a8 --- /dev/null +++ b/include/utils/Singleton.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_UTILS_SINGLETON_H +#define ANDROID_UTILS_SINGLETON_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/threads.h> + +namespace android { +// --------------------------------------------------------------------------- + +template <typename TYPE> +class Singleton +{ +public: + static TYPE& getInstance() { + Mutex::Autolock _l(sLock); + TYPE* instance = sInstance; + if (instance == 0) { + instance = new TYPE(); + sInstance = instance; + } + return *instance; + } + +protected: + ~Singleton() { }; + Singleton() { }; + +private: + Singleton(const Singleton&); + Singleton& operator = (const Singleton&); + static Mutex sLock; + static TYPE* sInstance; +}; + +/* + * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file + * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes, + * and avoid to have a copy of them in each compilation units Singleton<TYPE> + * is used. + */ + +#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \ + template class Singleton< TYPE >; \ + template< class TYPE > Mutex Singleton< TYPE >::sLock; \ + template<> TYPE* Singleton< TYPE >::sInstance(0); + + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_UTILS_SINGLETON_H + diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index a5698f2..16936e3 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -5,23 +5,21 @@ LOCAL_SRC_FILES:= \ clz.cpp.arm \ DisplayHardware/DisplayHardware.cpp \ DisplayHardware/DisplayHardwareBase.cpp \ - GPUHardware/GPUHardware.cpp \ BlurFilter.cpp.arm \ - CPUGauge.cpp \ + BufferAllocator.cpp \ Layer.cpp \ LayerBase.cpp \ LayerBuffer.cpp \ LayerBlur.cpp \ LayerBitmap.cpp \ LayerDim.cpp \ - LayerOrientationAnim.cpp \ - LayerOrientationAnimRotate.cpp \ - OrientationAnimation.cpp \ + MessageQueue.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ - Transform.cpp \ - VRamHeap.cpp + Transform.cpp +LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES # need "-lrt" on Linux simulator to pick up clock_gettime ifeq ($(TARGET_SIMULATOR),true) diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp new file mode 100644 index 0000000..cee8b64 --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.cpp @@ -0,0 +1,118 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <sys/mman.h> +#include <cutils/ashmem.h> +#include <cutils/log.h> + +#include <utils/Singleton.h> +#include <utils/String8.h> + +#include "BufferAllocator.h" + + +namespace android { +// --------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE( BufferAllocator ) + +Mutex BufferAllocator::sLock; +KeyedVector<buffer_handle_t, BufferAllocator::alloc_rec_t> BufferAllocator::sAllocList; + +BufferAllocator::BufferAllocator() + : mAllocDev(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + gralloc_open(module, &mAllocDev); + } +} + +BufferAllocator::~BufferAllocator() +{ + gralloc_close(mAllocDev); +} + +void BufferAllocator::dump(String8& result) const +{ + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + size_t total = 0; + const size_t SIZE = 512; + char buffer[SIZE]; + snprintf(buffer, SIZE, "Allocated buffers:\n"); + result.append(buffer); + const size_t c = list.size(); + for (size_t i=0 ; i<c ; i++) { + const alloc_rec_t& rec(list.valueAt(i)); + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u x %4u | %2d | 0x%08x\n", + list.keyAt(i), rec.size/1024.0f, + rec.w, rec.h, rec.format, rec.usage); + result.append(buffer); + total += rec.size; + } + snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f); + result.append(buffer); +} + +status_t BufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, + int usage, buffer_handle_t* handle, int32_t* stride) +{ + Mutex::Autolock _l(mLock); + + // we have a h/w allocator and h/w buffer is requested + status_t err = mAllocDev->alloc(mAllocDev, + w, h, format, usage, handle, stride); + LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", + w, h, format, usage, err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + alloc_rec_t rec; + rec.w = w; + rec.h = h; + rec.format = format; + rec.usage = usage; + rec.vaddr = 0; + rec.size = h * stride[0] * bytesPerPixel(format); + list.add(*handle, rec); + } + + return err; +} + +status_t BufferAllocator::free(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + + status_t err = mAllocDev->free(mAllocDev, handle); + LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); + + if (err == NO_ERROR) { + Mutex::Autolock _l(sLock); + KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + list.removeItem(handle); + } + + return err; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h new file mode 100644 index 0000000..a279ded --- /dev/null +++ b/libs/surfaceflinger/BufferAllocator.h @@ -0,0 +1,96 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_BUFFER_ALLOCATOR_H +#define ANDROID_BUFFER_ALLOCATOR_H + +#include <stdint.h> + +#include <cutils/native_handle.h> + +#include <utils/Errors.h> +#include <utils/KeyedVector.h> +#include <utils/threads.h> +#include <utils/Singleton.h> + +#include <ui/PixelFormat.h> + +#include <hardware/gralloc.h> + + +namespace android { +// --------------------------------------------------------------------------- + +class String8; + +class BufferAllocator : public Singleton<BufferAllocator> +{ +public: + enum { + USAGE_SW_READ_NEVER = GRALLOC_USAGE_SW_READ_NEVER, + USAGE_SW_READ_RARELY = GRALLOC_USAGE_SW_READ_RARELY, + USAGE_SW_READ_OFTEN = GRALLOC_USAGE_SW_READ_OFTEN, + USAGE_SW_READ_MASK = GRALLOC_USAGE_SW_READ_MASK, + + USAGE_SW_WRITE_NEVER = GRALLOC_USAGE_SW_WRITE_NEVER, + USAGE_SW_WRITE_RARELY = GRALLOC_USAGE_SW_WRITE_RARELY, + USAGE_SW_WRITE_OFTEN = GRALLOC_USAGE_SW_WRITE_OFTEN, + USAGE_SW_WRITE_MASK = GRALLOC_USAGE_SW_WRITE_MASK, + + USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK, + + USAGE_HW_TEXTURE = GRALLOC_USAGE_HW_TEXTURE, + USAGE_HW_RENDER = GRALLOC_USAGE_HW_RENDER, + USAGE_HW_2D = GRALLOC_USAGE_HW_2D, + USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK + }; + + static inline BufferAllocator& get() { return getInstance(); } + + + status_t alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, + buffer_handle_t* handle, int32_t* stride); + + status_t free(buffer_handle_t handle); + + void dump(String8& res) const; + +private: + struct alloc_rec_t { + uint32_t w; + uint32_t h; + PixelFormat format; + uint32_t usage; + void* vaddr; + size_t size; + }; + + static Mutex sLock; + static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList; + + friend class Singleton<BufferAllocator>; + BufferAllocator(); + ~BufferAllocator(); + + mutable Mutex mLock; + alloc_device_t *mAllocDev; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_BUFFER_ALLOCATOR_H diff --git a/libs/surfaceflinger/CPUGauge.cpp b/libs/surfaceflinger/CPUGauge.cpp deleted file mode 100644 index 74a9270..0000000 --- a/libs/surfaceflinger/CPUGauge.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "CPUGauge" - -#include <stdint.h> -#include <limits.h> -#include <sys/types.h> -#include <math.h> - -#include <utils/threads.h> -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/PixelFormat.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/DisplayInfo.h> -#include <ui/ISurfaceComposer.h> -#include <ui/ISurfaceFlingerClient.h> - -#include <pixelflinger/pixelflinger.h> - -#include "CPUGauge.h" - -namespace android { - -CPUGauge::CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval, - int clock, - int refclock) - : Thread(false), - mInterval(interval), mClock(clock), mRefClock(refclock), - mReferenceTime(0), - mReferenceWorkingTime(0), mCpuUsage(0), - mRefIdleTime(0), mIdleTime(0) -{ - mFd = fopen("/proc/stat", "r"); - setvbuf(mFd, NULL, _IONBF, 0); - - mSession = SurfaceComposerClient::clientForConnection( - composer->createConnection()->asBinder()); -} - -CPUGauge::~CPUGauge() -{ - fclose(mFd); -} - -const sp<SurfaceComposerClient>& CPUGauge::session() const -{ - return mSession; -} - -void CPUGauge::onFirstRef() -{ - run("CPU Gauge"); -} - -status_t CPUGauge::readyToRun() -{ - LOGI("Starting CPU gauge..."); - return NO_ERROR; -} - -bool CPUGauge::threadLoop() -{ - DisplayInfo dinfo; - session()->getDisplayInfo(0, &dinfo); - sp<Surface> s(session()->createSurface(getpid(), 0, dinfo.w, 4, PIXEL_FORMAT_OPAQUE)); - session()->openTransaction(); - s->setLayer(INT_MAX); - session()->closeTransaction(); - - static const GGLfixed colors[4][4] = { - { 0x00000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x10000, 0x00000, 0x10000 }, - { 0x10000, 0x00000, 0x00000, 0x10000 }, - { 0x00000, 0x00000, 0x00000, 0x10000 }, - }; - - GGLContext* gl; - gglInit(&gl); - gl->activeTexture(gl, 0); - gl->disable(gl, GGL_TEXTURE_2D); - gl->disable(gl, GGL_BLEND); - - const int w = dinfo.w; - - while(!exitPending()) - { - mLock.lock(); - const float cpuUsage = this->cpuUsage(); - const float totalCpuUsage = 1.0f - idle(); - mLock.unlock(); - - Surface::SurfaceInfo info; - s->lock(&info); - GGLSurface fb; - fb.version = sizeof(GGLSurface); - fb.width = info.w; - fb.height = info.h; - fb.stride = info.w; - fb.format = info.format; - fb.data = (GGLubyte*)info.bits; - - gl->colorBuffer(gl, &fb); - gl->color4xv(gl, colors[3]); - gl->recti(gl, 0, 0, w, 4); - gl->color4xv(gl, colors[2]); // red - gl->recti(gl, 0, 0, int(totalCpuUsage*w), 2); - gl->color4xv(gl, colors[0]); // green - gl->recti(gl, 0, 2, int(cpuUsage*w), 4); - - s->unlockAndPost(); - - usleep(ns2us(mInterval)); - } - - gglUninit(gl); - return false; -} - -void CPUGauge::sample() -{ - if (mLock.tryLock() == NO_ERROR) { - const nsecs_t now = systemTime(mRefClock); - const nsecs_t referenceTime = now-mReferenceTime; - if (referenceTime >= mInterval) { - const float reftime = 1.0f / referenceTime; - const nsecs_t nowWorkingTime = systemTime(mClock); - - char buf[256]; - fgets(buf, 256, mFd); - rewind(mFd); - char *str = buf+5; - char const * const usermode = strsep(&str, " "); (void)usermode; - char const * const usernice = strsep(&str, " "); (void)usernice; - char const * const systemmode = strsep(&str, " ");(void)systemmode; - char const * const idle = strsep(&str, " "); - const nsecs_t nowIdleTime = atoi(idle) * 10000000LL; - mIdleTime = float(nowIdleTime - mRefIdleTime) * reftime; - mRefIdleTime = nowIdleTime; - - const nsecs_t workingTime = nowWorkingTime - mReferenceWorkingTime; - const float newCpuUsage = float(workingTime) * reftime; - if (mCpuUsage != newCpuUsage) { - mCpuUsage = newCpuUsage; - mReferenceWorkingTime = nowWorkingTime; - mReferenceTime = now; - } - } - mLock.unlock(); - } -} - - -}; // namespace android diff --git a/libs/surfaceflinger/CPUGauge.h b/libs/surfaceflinger/CPUGauge.h deleted file mode 100644 index 5bb53c0..0000000 --- a/libs/surfaceflinger/CPUGauge.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_CPUGAUGE_H -#define ANDROID_CPUGAUGE_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Timers.h> - -#include <ui/SurfaceComposerClient.h> - -namespace android { - -class CPUGauge : public Thread -{ -public: - CPUGauge( const sp<ISurfaceComposer>& composer, - nsecs_t interval=s2ns(1), - int clock=SYSTEM_TIME_THREAD, - int refclock=SYSTEM_TIME_MONOTONIC); - - ~CPUGauge(); - - const sp<SurfaceComposerClient>& session() const; - - void sample(); - - inline float cpuUsage() const { return mCpuUsage; } - inline float idle() const { return mIdleTime; } - -private: - virtual void onFirstRef(); - virtual status_t readyToRun(); - virtual bool threadLoop(); - - Mutex mLock; - - sp<SurfaceComposerClient> mSession; - - const nsecs_t mInterval; - const int mClock; - const int mRefClock; - - nsecs_t mReferenceTime; - nsecs_t mReferenceWorkingTime; - float mCpuUsage; - nsecs_t mRefIdleTime; - float mIdleTime; - FILE* mFd; -}; - - -}; // namespace android - -#endif // ANDROID_CPUGAUGE_H diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index f14d7e9..25e351c 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -23,18 +21,23 @@ #include <cutils/properties.h> +#include <utils/RefBase.h> #include <utils/Log.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/PixelFormat.h> +#include <ui/FramebufferNativeWindow.h> #include <GLES/gl.h> +#include <EGL/egl.h> #include <EGL/eglext.h> +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardware.h" #include <hardware/copybit.h> #include <hardware/overlay.h> +#include <hardware/gralloc.h> using namespace android; @@ -108,17 +111,28 @@ PixelFormat DisplayHardware::getFormat() const { return mFormat; } void DisplayHardware::init(uint32_t dpy) { + hw_module_t const* module; + + mNativeWindow = new FramebufferNativeWindow(); + + mOverlayEngine = NULL; + if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { + overlay_control_open(module, &mOverlayEngine); + } + + framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); + + PixelFormatInfo fbFormatInfo; + getPixelFormatInfo(PixelFormat(fbDev->format), &fbFormatInfo); + // initialize EGL const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, + EGL_BUFFER_SIZE, fbFormatInfo.bitsPerPixel, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h, dummy; - EGLint numConfigs, n; - EGLConfig config; + EGLint numConfigs=0, n=0; EGLSurface surface; EGLContext context; mFlags = 0; @@ -129,7 +143,31 @@ void DisplayHardware::init(uint32_t dpy) EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); - eglChooseConfig(display, attribs, &config, 1, &n); + + // Get all the "potential match" configs... + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(display, attribs, configs, numConfigs, &n); + LOGE_IF(n<=0, "no EGLConfig available!"); + EGLConfig config = configs[0]; + if (n > 1) { + // if there is more than one candidate, go through the list + // and pick one that matches our framebuffer format + int fbSzA = fbFormatInfo.getSize(PixelFormatInfo::INDEX_ALPHA); + int fbSzR = fbFormatInfo.getSize(PixelFormatInfo::INDEX_RED); + int fbSzG = fbFormatInfo.getSize(PixelFormatInfo::INDEX_GREEN); + int fbSzB = fbFormatInfo.getSize(PixelFormatInfo::INDEX_BLUE); + for (int i=0 ; i<n ; i++) { + EGLint r,g,b,a; + eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &a); + if (fbSzA == a && fbSzR == r && fbSzG == g && fbSzB == b) { + config = configs[i]; + } + } + } + delete [] configs; /* * Gather EGL extensions @@ -145,12 +183,11 @@ void DisplayHardware::init(uint32_t dpy) LOGI("extensions: %s", egl_extensions); LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - // TODO: get this from the devfb driver (probably should be HAL module) - mFlags |= SWAP_RECTANGLE_EXTENSION; - - // TODO: get the real "update_on_demand" behavior (probably should be HAL module) - mFlags |= UPDATE_ON_DEMAND; + if (mNativeWindow->isUpdateOnDemand()) { + mFlags |= UPDATE_ON_DEMAND; + } + if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) mFlags |= SLOW_CONFIG; @@ -160,33 +197,22 @@ void DisplayHardware::init(uint32_t dpy) * Create our main surface */ - mDisplaySurface = new EGLDisplaySurface(); - - surface = eglCreateWindowSurface(display, config, mDisplaySurface.get(), NULL); - //checkEGLErrors("eglCreateDisplaySurfaceANDROID"); + surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); + checkEGLErrors("eglCreateDisplaySurfaceANDROID"); if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; } } - - GLint value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_HORIZONTAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiX = 160.0f; - } else { - mDpiX = 25.4f * float(value)/EGL_DISPLAY_SCALING; - } - value = EGL_UNKNOWN; - eglQuerySurface(display, surface, EGL_VERTICAL_RESOLUTION, &value); - if (value == EGL_UNKNOWN) { - mDpiY = 160.0f; - } else { - mDpiY = 25.4f * float(value)/EGL_DISPLAY_SCALING; + + if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) { + mFlags |= SWAP_RECTANGLE; } - mRefreshRate = 60.f; // TODO: get the real refresh rate - + + mDpiX = mNativeWindow->xdpi; + mDpiX = mNativeWindow->ydpi; + mRefreshRate = fbDev->fps; char property[PROPERTY_VALUE_MAX]; if (property_get("ro.sf.lcd_density", property, NULL) <= 0) { @@ -225,7 +251,10 @@ void DisplayHardware::init(uint32_t dpy) if (strstr(gl_extensions, "GL_OES_draw_texture")) { mFlags |= DRAW_TEXTURE_EXTENSION; } - if (strstr(gl_extensions, "GL_ANDROID_direct_texture")) { + if (strstr( gl_extensions, "GL_OES_EGL_image") && + (strstr(egl_extensions, "EGL_KHR_image_base") || + strstr(egl_extensions, "EGL_KHR_image")) && + strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { mFlags |= DIRECT_TEXTURE; } @@ -236,19 +265,8 @@ void DisplayHardware::init(uint32_t dpy) mConfig = config; mSurface = surface; mContext = context; - mFormat = GGL_PIXEL_FORMAT_RGB_565; - - hw_module_t const* module; - - mBlitEngine = NULL; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - mOverlayEngine = NULL; - if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { - overlay_control_open(module, &mOverlayEngine); - } + mFormat = fbDev->format; + mPageFlipCount = 0; } /* @@ -262,7 +280,6 @@ void DisplayHardware::fini() { eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglTerminate(mDisplay); - copybit_close(mBlitEngine); overlay_control_close(mOverlayEngine); } @@ -276,28 +293,8 @@ void DisplayHardware::acquireScreen() const DisplayHardwareBase::acquireScreen(); } -void DisplayHardware::getDisplaySurface(copybit_image_t* img) const -{ - img->w = mDisplaySurface->stride; - img->h = mDisplaySurface->height; - img->format = mDisplaySurface->format; - img->offset = mDisplaySurface->offset; - img->base = (void*)mDisplaySurface->base; - img->fd = mDisplaySurface->fd; -} - -void DisplayHardware::getDisplaySurface(GGLSurface* fb) const -{ - fb->version= sizeof(GGLSurface); - fb->width = mDisplaySurface->width; - fb->height = mDisplaySurface->height; - fb->stride = mDisplaySurface->stride; - fb->format = mDisplaySurface->format; - fb->data = (GGLubyte*)mDisplaySurface->base + mDisplaySurface->offset; -} - uint32_t DisplayHardware::getPageFlipCount() const { - return mDisplaySurface->getPageFlipCount(); + return mPageFlipCount; } /* @@ -311,21 +308,19 @@ void DisplayHardware::flip(const Region& dirty) const EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; - Region newDirty(dirty); - newDirty.andSelf(Rect(mWidth, mHeight)); - - if (mFlags & BUFFER_PRESERVED) { - const Region copyback(mDirty.subtract(newDirty)); - mDirty = newDirty; - mDisplaySurface->copyFrontToBack(copyback); - } - - if (mFlags & SWAP_RECTANGLE_EXTENSION) { + if (mFlags & SWAP_RECTANGLE) { + Region newDirty(dirty); + newDirty.andSelf(Rect(mWidth, mHeight)); const Rect& b(newDirty.bounds()); - mDisplaySurface->setSwapRectangle( + eglSetSwapRectangleANDROID(dpy, surface, b.left, b.top, b.width(), b.height()); - } + } + if (mFlags & UPDATE_ON_DEMAND) { + mNativeWindow->setUpdateRectangle(dirty.bounds()); + } + + mPageFlipCount++; eglSwapBuffers(dpy, surface); checkEGLErrors("eglSwapBuffers"); @@ -345,9 +340,9 @@ void DisplayHardware::makeCurrent() const } void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { - mDisplaySurface->copyFrontToImage(front); + // FIXME: we need to get rid of this } void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { - mDisplaySurface->copyBackToImage(front); + // FIXME: we need to get rid of this } diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index 550a4d1..c3dbff1 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -22,31 +22,35 @@ #include <ui/PixelFormat.h> #include <ui/Region.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <pixelflinger/pixelflinger.h> #include "DisplayHardware/DisplayHardwareBase.h" struct overlay_control_device_t; -struct copybit_device_t; +struct framebuffer_device_t; struct copybit_image_t; -struct copybit_t; namespace android { -class EGLDisplaySurface; +class FramebufferNativeWindow; class DisplayHardware : public DisplayHardwareBase { public: enum { DIRECT_TEXTURE = 0x00000002, - SWAP_RECTANGLE_EXTENSION= 0x00000004, COPY_BITS_EXTENSION = 0x00000008, NPOT_EXTENSION = 0x00000100, DRAW_TEXTURE_EXTENSION = 0x00000200, BUFFER_PRESERVED = 0x00010000, UPDATE_ON_DEMAND = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software + SWAP_RECTANGLE = 0x00080000, }; DisplayHardware( @@ -73,10 +77,7 @@ public: void makeCurrent() const; uint32_t getPageFlipCount() const; - void getDisplaySurface(copybit_image_t* img) const; - void getDisplaySurface(GGLSurface* fb) const; EGLDisplay getEGLDisplay() const { return mDisplay; } - copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } void copyFrontToImage(const copybit_image_t& front) const; @@ -102,9 +103,9 @@ private: int mHeight; PixelFormat mFormat; uint32_t mFlags; - mutable Region mDirty; - sp<EGLDisplaySurface> mDisplaySurface; - copybit_device_t* mBlitEngine; + mutable uint32_t mPageFlipCount; + + sp<FramebufferNativeWindow> mNativeWindow; overlay_control_device_t* mOverlayEngine; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp index f75e5c2..1d09f84 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <assert.h> #include <errno.h> #include <stdlib.h> diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 96395a8..5b260c4 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -14,26 +14,24 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <cutils/properties.h> +#include <cutils/native_handle.h> #include <utils/Errors.h> #include <utils/Log.h> #include <utils/StopWatch.h> #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> +#include <ui/Surface.h> #include "clz.h" #include "Layer.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -54,8 +52,7 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) mSecure(false), mFrontBufferIndex(1), mNeedsBlending(true), - mResizeTransactionDone(false), - mTextureName(-1U), mTextureWidth(0), mTextureHeight(0) + mResizeTransactionDone(false) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. @@ -63,11 +60,22 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) Layer::~Layer() { - client->free(clientIndex()); - // this should always be called from the OpenGL thread - if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); + destroy(); + // the actual buffers will be destroyed here +} + +void Layer::destroy() +{ + for (int i=0 ; i<NUM_BUFFERS ; i++) { + if (mTextures[i].name != -1U) { + glDeleteTextures(1, &mTextures[i].name); + mTextures[i].name = -1U; + } + if (mTextures[i].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[i].image); + mTextures[i].image = EGL_NO_IMAGE_KHR; + } } } @@ -79,11 +87,19 @@ void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) lcblk->flags |= eNoCopyBack; } -sp<LayerBaseClient::Surface> Layer::getSurface() const +sp<LayerBaseClient::Surface> Layer::createSurface() const { return mSurface; } +status_t Layer::ditch() +{ + // the layer is not on screen anymore. free as much resources as possible + mSurface.clear(); + destroy(); + return NO_ERROR; +} + status_t Layer::setBuffers( Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) @@ -92,71 +108,115 @@ status_t Layer::setBuffers( Client* client, status_t err = getPixelFormatInfo(format, &info); if (err) return err; - // TODO: if eHardware is explicitly requested, we should fail - // on systems where we can't allocate memory that can be used with - // DMA engines for instance. - - // FIXME: we always ask for hardware for now (this should come from copybit) - flags |= ISurfaceComposer::eHardware; + uint32_t bufferFlags = 0; + if (flags & ISurfaceComposer::eGPU) + bufferFlags |= Buffer::GPU; - const uint32_t memory_flags = flags & - (ISurfaceComposer::eGPU | - ISurfaceComposer::eHardware | - ISurfaceComposer::eSecure); - - // pixel-alignment. the final alignment may be bigger because - // we always force a 4-byte aligned bpr. - uint32_t alignment = 1; + if (flags & ISurfaceComposer::eSecure) + bufferFlags |= Buffer::SECURE; - if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) { - // FIXME: this value should come from the h/w - alignment = 8; + /* FIXME we need this code for msm7201A + if (bufferFlags & Buffer::GPU) { // FIXME: this is msm7201A specific, as its GPU only supports // BGRA_8888. if (format == PIXEL_FORMAT_RGBA_8888) { format = PIXEL_FORMAT_BGRA_8888; } } + */ - mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; + mSecure = (bufferFlags & Buffer::SECURE) ? true : false; mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; - sp<MemoryDealer> allocators[2]; for (int i=0 ; i<2 ; i++) { - allocators[i] = client->createAllocator(memory_flags); - if (allocators[i] == 0) - return NO_MEMORY; - mBuffers[i].init(allocators[i]); - int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS); - if (err != NO_ERROR) + err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags); + if (err != NO_ERROR) { return err; - mBuffers[i].clear(); // clear the bits for security - mBuffers[i].getInfo(lcblk->surface + i); + } } - - mSurface = new Surface(clientIndex(), - allocators[0]->getMemoryHeap(), - allocators[1]->getMemoryHeap(), - mIdentity); - + mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); return NO_ERROR; } void Layer::reloadTexture(const Region& dirty) { - if (UNLIKELY(mTextureName == -1U)) { - // create the texture name the first time - // can't do that in the ctor, because it runs in another thread. - mTextureName = createTexture(); + const sp<Buffer>& buffer(frontBuffer().getBuffer()); + if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { + int index = mFrontBufferIndex; + if (LIKELY(!mTextures[index].dirty)) { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } else { + // we need to recreate the texture + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + + // create the new texture name if needed + if (UNLIKELY(mTextures[index].name == -1U)) { + mTextures[index].name = createTexture(); + } else { + glBindTexture(GL_TEXTURE_2D, mTextures[index].name); + } + + // free the previous image + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(dpy, mTextures[index].image); + mTextures[index].image = EGL_NO_IMAGE_KHR; + } + + // construct an EGL_NATIVE_BUFFER_ANDROID + android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); + + // create the new EGLImageKHR + const EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, EGL_NONE + }; + mTextures[index].image = eglCreateImageKHR( + dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)clientBuf, attrs); + + LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, + "eglCreateImageKHR() failed. err=0x%4x", + eglGetError()); + + if (mTextures[index].image != EGL_NO_IMAGE_KHR) { + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, + (GLeglImageOES)mTextures[index].image); + GLint error = glGetError(); + if (UNLIKELY(error != GL_NO_ERROR)) { + // this failed, for instance, because we don't support + // NPOT. + // FIXME: do something! + mFlags &= ~DisplayHardware::DIRECT_TEXTURE; + } else { + // Everything went okay! + mTextures[index].dirty = false; + } + } + } + } else { + GGLSurface t; + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + LOGE_IF(res, "error %d (%s) locking buffer %p", + res, strerror(res), buffer.get()); + if (res == NO_ERROR) { + if (UNLIKELY(mTextures[0].name == -1U)) { + mTextures[0].name = createTexture(); + } + loadTexture(dirty, mTextures[0].name, t, + mTextures[0].width, mTextures[0].height); + buffer->unlock(); + } } - const GGLSurface& t(frontBuffer().surface()); - loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight); } void Layer::onDraw(const Region& clip) const { - if (UNLIKELY(mTextureName == -1LU)) { - //LOGW("Layer %p doesn't have a texture", this); + const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? + mFrontBufferIndex : 0; + GLuint textureName = mTextures[index].name; + + if (UNLIKELY(textureName == -1LU)) { + LOGW("Layer %p doesn't have a texture", this); // the texture has not been created yet, this Layer has // in fact never been drawn into. this happens frequently with // SurfaceView. @@ -164,63 +224,65 @@ void Layer::onDraw(const Region& clip) const return; } - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const LayerBitmap& front(frontBuffer()); - const GGLSurface& t(front.surface()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - const State& s(drawingState()); - - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - front.getBitmapSurface(&src); - copybit_rect_t srect = { 0, 0, t.width, t.height }; - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation()); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - s.flags & ISurfaceComposer::eLayerDither ? - COPYBIT_ENABLE : COPYBIT_DISABLE); - - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - drawWithOpenGL(clip, mTextureName, t); - } + GGLSurface t; + sp<const Buffer> buffer(frontBuffer().getBuffer()); + drawWithOpenGL(clip, textureName, buffer); } -status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h) +sp<SurfaceBuffer> Layer::peekBuffer() { + /* + * This is called from the client's Surface::lock(), after it locked + * the surface successfully. We're therefore guaranteed that the + * back-buffer is not in use by ourselves. + * Of course, we need to validate all this, which is not trivial. + * + * FIXME: A resize could happen at any time here. What to do about this? + * - resize() form post() + * - resize() from doTransaction() + * + * We'll probably need an internal lock for this. + * + * + * TODO: We need to make sure that post() doesn't swap + * the buffers under us. + */ + + // it's okay to read swapState for the purpose of figuring out the + // backbuffer index, which cannot change (since the app has locked it). + const uint32_t state = lcblk->swapState; + const int32_t backBufferIndex = layer_cblk_t::backBuffer(state); + + // get rid of the EGL image, since we shouldn't need it anymore + // (note that we're in a different thread than where it is being used) + if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) { + EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); + eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image); + mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR; + } + + LayerBitmap& layerBitmap(mBuffers[backBufferIndex]); + sp<SurfaceBuffer> buffer = layerBitmap.allocate(); + LOGD_IF(DEBUG_RESIZE, - "reallocateBuffer (layer=%p), " - "requested (%dx%d), " - "index=%d, (%dx%d), (%dx%d)", - this, - int(w), int(h), - int(index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); - - status_t err = mBuffers[index].resize(w, h); - if (err == NO_ERROR) { - mBuffers[index].getInfo(lcblk->surface + index); + "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)", + this, backBufferIndex, + layerBitmap.getWidth(), + layerBitmap.getHeight(), + layerBitmap.getBuffer()->getWidth(), + layerBitmap.getBuffer()->getHeight()); + + if (UNLIKELY(buffer == 0)) { + // XXX: what to do, what to do? } else { - LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", - index, w, h, err, strerror(err)); - // XXX: what to do, what to do? We could try to free some - // hidden surfaces, instead of killing this one? + // texture is now dirty... + mTextures[backBufferIndex].dirty = true; + // ... so it the visible region (because we consider the surface's + // buffer size for visibility calculations) + forceVisibilityTransaction(); + mFlinger->setTransactionFlags(eTraversalNeeded); } - return err; + return buffer; } uint32_t Layer::doTransaction(uint32_t flags) @@ -232,7 +294,7 @@ uint32_t Layer::doTransaction(uint32_t flags) // that the size changed back to its previous value before the buffer // was resized (in the eLocked case below), in which case, we still // need to execute the code below so the clients have a chance to be - // release. resze() deals with the fact that the size can be the same. + // release. resize() deals with the fact that the size can be the same. /* * Various states we could be in... @@ -276,8 +338,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // if we get there we're pretty screwed. the only reasonable // thing to do is to pretend we should do the resize since // backbufferChanged is set (this also will give a chance to @@ -299,8 +361,8 @@ uint32_t Layer::doTransaction(uint32_t flags) int(temp.w), int(temp.h), int(drawingState().w), int(drawingState().h), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); if (state & eLocked) { // if the buffer is locked, we can't resize anything because @@ -314,7 +376,8 @@ uint32_t Layer::doTransaction(uint32_t flags) status_t err = resize(clientBackBufferIndex, temp.w, temp.h, "transaction"); if (err == NO_ERROR) { - const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; + const uint32_t mask = clientBackBufferIndex ? + eResizeBuffer1 : eResizeBuffer0; android_atomic_and(~mask, &(lcblk->swapState)); // since a buffer became available, we can let the client go... mFlinger->scheduleBroadcast(client); @@ -353,14 +416,15 @@ status_t Layer::resize( { /* * handle resize (backbuffer and frontbuffer reallocation) + * this is called from post() or from doTransaction() */ const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]); // if the new (transaction) size is != from the the backbuffer // then we need to reallocate the backbuffer - bool backbufferChanged = (clientBackBuffer.width() != width) || - (clientBackBuffer.height() != height); + bool backbufferChanged = (clientBackBuffer.getWidth() != width) || + (clientBackBuffer.getHeight() != height); LOGD_IF(!backbufferChanged, "(%s) eResizeRequested (layer=%p), but size not changed: " @@ -372,18 +436,28 @@ status_t Layer::resize( int(currentState().w), int(currentState().h), long(lcblk->swapState), int(clientBackBufferIndex), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // this can happen when changing the size back and forth quickly status_t err = NO_ERROR; if (backbufferChanged) { - err = reallocateBuffer(clientBackBufferIndex, width, height); - } - if (UNLIKELY(err != NO_ERROR)) { - // couldn't reallocate the surface - android_atomic_write(eInvalidSurface, &lcblk->swapState); - memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t)); + + LOGD_IF(DEBUG_RESIZE, + "resize (layer=%p), requested (%dx%d), " + "index=%d, (%dx%d), (%dx%d)", + this, int(width), int(height), int(clientBackBufferIndex), + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); + + err = mBuffers[clientBackBufferIndex].setSize(width, height); + if (UNLIKELY(err != NO_ERROR)) { + // This really should never happen + LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", + clientBackBufferIndex, width, height, err, strerror(err)); + // couldn't reallocate the surface + android_atomic_write(eInvalidSurface, &lcblk->swapState); + } } return err; } @@ -457,15 +531,21 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); *previousSate = oldValue; - + const int32_t index = (newValue & eIndex) ^ 1; mFrontBufferIndex = index; + /* NOTE: it's safe to set this flag here because this is only touched + * from LayerBitmap::allocate(), which by construction cannot happen + * while we're in post(). + */ + lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty; + // ... post the new front-buffer Region dirty(lcblk->region + index); - dirty.andSelf(frontBuffer().bounds()); + dirty.andSelf(frontBuffer().getBounds()); - //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", + //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", // oldValue, newValue, mFrontBufferIndex); //dirty.dump("dirty"); @@ -476,8 +556,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) "index=%d, (%dx%d), (%dx%d)", this, newValue, int(1-index), - int(mBuffers[0].width()), int(mBuffers[0].height()), - int(mBuffers[1].width()), int(mBuffers[1].height())); + int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), + int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); // here, we just posted the surface and we have resolved // the front/back buffer indices. The client is blocked, so @@ -522,8 +602,8 @@ Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) Point Layer::getPhysicalSize() const { - const LayerBitmap& front(frontBuffer()); - return Point(front.width(), front.height()); + sp<const Buffer> front(frontBuffer().getBuffer()); + return Point(front->getWidth(), front->getHeight()); } void Layer::unlockPageFlip( @@ -561,6 +641,27 @@ void Layer::finishPageFlip() mFlinger->scheduleBroadcast(client); } +// --------------------------------------------------------------------------- + +Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<Layer>& owner) + : Surface(flinger, id, owner->getIdentity(), owner) +{ +} + +Layer::SurfaceLayer::~SurfaceLayer() +{ +} + +sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer() +{ + sp<SurfaceBuffer> buffer = 0; + sp<Layer> owner(getOwner()); + if (owner != 0) { + buffer = owner->peekBuffer(); + } + return buffer; +} // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 2867f2b..e16d9f4 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -27,6 +27,11 @@ #include <pixelflinger/pixelflinger.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "LayerBitmap.h" #include "LayerBase.h" #include "Transform.h" @@ -42,6 +47,8 @@ class FreezeLock; // --------------------------------------------------------------------------- +const int NUM_BUFFERS = 2; + class Layer : public LayerBaseClient { public: @@ -56,7 +63,7 @@ public: virtual ~Layer(); inline PixelFormat pixelFormat() const { - return frontBuffer().pixelFormat(); + return frontBuffer().getPixelFormat(); } status_t setBuffers( Client* client, @@ -73,8 +80,8 @@ public: virtual void finishPageFlip(); virtual bool needsBlending() const { return mNeedsBlending; } virtual bool isSecure() const { return mSecure; } - virtual GLuint getTextureName() const { return mTextureName; } - virtual sp<Surface> getSurface() const; + virtual sp<Surface> createSurface() const; + virtual status_t ditch(); const LayerBitmap& getBuffer(int i) const { return mBuffers[i]; } LayerBitmap& getBuffer(int i) { return mBuffers[i]; } @@ -96,21 +103,46 @@ private: status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what); Region post(uint32_t* oldState, bool& recomputeVisibleRegions); - status_t reallocateBuffer(int32_t index, uint32_t w, uint32_t h); - + sp<SurfaceBuffer> peekBuffer(); + void destroy(); + + + class SurfaceLayer : public LayerBaseClient::Surface + { + public: + SurfaceLayer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<Layer>& owner); + ~SurfaceLayer(); + + private: + virtual sp<SurfaceBuffer> getBuffer(); + + sp<Layer> getOwner() const { + return static_cast<Layer*>(Surface::getOwner().get()); + } + }; + friend class SurfaceLayer; + + struct Texture { + Texture() : name(-1U), width(0), height(0), image(EGL_NO_IMAGE_KHR), + dirty(true) { } + GLuint name; + GLuint width; + GLuint height; + EGLImageKHR image; + bool dirty; + }; + sp<Surface> mSurface; bool mSecure; - LayerBitmap mBuffers[2]; + LayerBitmap mBuffers[NUM_BUFFERS]; + Texture mTextures[NUM_BUFFERS]; int32_t mFrontBufferIndex; bool mNeedsBlending; bool mResizeTransactionDone; Region mPostedDirtyRegion; sp<FreezeLock> mFreezeLock; - - GLuint mTextureName; - GLuint mTextureWidth; - GLuint mTextureHeight; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 0cf53f7..c678711 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -14,14 +14,14 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <utils/Errors.h> #include <utils/Log.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> #include <GLES/gl.h> #include <GLES/glext.h> @@ -53,8 +53,6 @@ const char* const LayerBaseClient::typeID = "LayerBaseClient"; // --------------------------------------------------------------------------- -Vector<GLuint> LayerBase::deletedTextures; - int32_t LayerBase::sIdentity = 0; LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) @@ -62,7 +60,6 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display) mFlinger(flinger), mTransformed(false), mOrientation(0), - mCanUseCopyBit(false), mTransactionFlags(0), mPremultipliedAlpha(true), mIdentity(uint32_t(android_atomic_inc(&sIdentity))), @@ -265,43 +262,6 @@ void LayerBase::validateVisibility(const Transform& planeTransform) mTransformed = transformed; mLeft = tr.tx(); mTop = tr.ty(); - - // see if we can/should use 2D h/w with the new configuration - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - const int step = copybit->get(copybit, COPYBIT_ROTATION_STEP_DEG); - const int scaleBits = copybit->get(copybit, COPYBIT_SCALING_FRAC_BITS); - mCanUseCopyBit = true; - if ((mOrientation < 0) && (step > 1)) { - // arbitrary orientations not supported - mCanUseCopyBit = false; - } else if ((mOrientation > 0) && (step > 90)) { - // 90 deg rotations not supported - mCanUseCopyBit = false; - } else if ((tr.getType() & SkMatrix::kScale_Mask) && (scaleBits < 12)) { - // arbitrary scaling not supported - mCanUseCopyBit = false; - } -#if HONOR_PREMULTIPLIED_ALPHA - else if (needsBlending() && mPremultipliedAlpha) { - // pre-multiplied alpha not supported - mCanUseCopyBit = false; - } -#endif - else { - // here, we determined we can use copybit - if (tr.getType() & SkMatrix::kScale_Mask) { - // and we have scaling - if (!transparentRegionScreen.isRect()) { - // we punt because blending is cheap (h/w) and the region is - // complex, which may causes artifacts when copying - // scaled content - transparentRegionScreen.clear(); - } - } - } - } } void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) @@ -329,8 +289,9 @@ void LayerBase::invalidate() void LayerBase::drawRegion(const Region& reg) const { - Region::iterator iterator(reg); - if (iterator) { + Region::const_iterator it = reg.begin(); + Region::const_iterator const end = reg.end(); + if (it != end) { Rect r; const DisplayHardware& hw(graphicPlane(0).displayHardware()); const int32_t fbWidth = hw.getWidth(); @@ -338,7 +299,8 @@ void LayerBase::drawRegion(const Region& reg) const const GLshort vertices[][2] = { { 0, 0 }, { fbWidth, 0 }, { fbWidth, fbHeight }, { 0, fbHeight } }; glVertexPointer(2, GL_SHORT, 0, vertices); - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -403,12 +365,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); - Rect r; - Region::iterator iterator(clip); - if (iterator) { + + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { glEnable(GL_SCISSOR_TEST); glVertexPointer(2, GL_FIXED, 0, mVertices); - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -417,12 +381,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const } void LayerBase::drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& t, int transform) const + GLint textureName, const sp<const Buffer>& buffer, int transform) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); - + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + // bind our texture validateTexture(textureName); glEnable(GL_TEXTURE_2D); @@ -472,8 +438,9 @@ void LayerBase::drawWithOpenGL(const Region& clip, || !(mFlags & DisplayHardware::DRAW_TEXTURE_EXTENSION) )) { //StopWatch watch("GL transformed"); - Region::iterator iterator(clip); - if (iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { // always use high-quality filtering with fast configurations bool fast = !(mFlags & DisplayHardware::SLOW_CONFIG); if (!fast && s.flags & ISurfaceComposer::eLayerFilter) { @@ -497,14 +464,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface - GLuint tw = 1 << (31 - clz(t.width)); - GLuint th = 1 << (31 - clz(t.height)); - if (tw < t.width) tw <<= 1; - if (th < t.height) th <<= 1; + GLuint tw = 1 << (31 - clz(width)); + GLuint th = 1 << (31 - clz(height)); + if (tw < width) tw <<= 1; + if (th < height) th <<= 1; // this divide should be relatively fast because it's // a power-of-two (optimized path in libgcc) - GLfloat ws = GLfloat(t.width) /tw; - GLfloat hs = GLfloat(t.height)/th; + GLfloat ws = GLfloat(width) /tw; + GLfloat hs = GLfloat(height)/th; glScalef(ws, hs, 1.0f); } @@ -512,8 +479,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, texCoords); - Rect r; - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -526,18 +493,19 @@ void LayerBase::drawWithOpenGL(const Region& clip, glDisableClientState(GL_TEXTURE_COORD_ARRAY); } } else { - Region::iterator iterator(clip); - if (iterator) { - Rect r; - GLint crop[4] = { 0, t.height, t.width, -t.height }; + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { + GLint crop[4] = { 0, height, width, -height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); int x = tx(); int y = ty(); - y = fbHeight - (y + t.height); - while (iterator.iterate(&r)) { + y = fbHeight - (y + height); + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, t.width, t.height); + glDrawTexiOES(x, y, 0, width, height); } } } @@ -565,8 +533,7 @@ void LayerBase::loadTexture(const Region& dirty, /* * In OpenGL ES we can't specify a stride with glTexImage2D (however, - * GL_UNPACK_ALIGNMENT is 4, which in essence allows a limited form of - * stride). + * GL_UNPACK_ALIGNMENT is a limited form of stride). * So if the stride here isn't representable with GL_UNPACK_ALIGNMENT, we * need to do something reasonable (here creating a bigger texture). * @@ -579,9 +546,11 @@ void LayerBase::loadTexture(const Region& dirty, * * This should never be a problem with POT textures */ - - tw += (((t.stride - tw) * bytesPerPixel(t.format)) / 4); - + + int unpack = __builtin_ctz(t.stride * bytesPerPixel(t.format)); + unpack = 1 << ((unpack > 3) ? 3 : unpack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + /* * round to POT if needed */ @@ -594,106 +563,78 @@ void LayerBase::loadTexture(const Region& dirty, texture_h = 1 << (31 - clz(t.height)); if (texture_w < t.width) texture_w <<= 1; if (texture_h < t.height) texture_h <<= 1; - if (texture_w != tw || texture_h != th) { - // we can't use DIRECT_TEXTURE since we changed the size - // of the texture - flags &= ~DisplayHardware::DIRECT_TEXTURE; - } } - - if (flags & DisplayHardware::DIRECT_TEXTURE) { - // here we're guaranteed that texture_{w|h} == t{w|h} - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGB, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0, - GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, t.data); - } else if (t.format == GGL_PIXEL_FORMAT_BGRA_8888) { - // TODO: add GL_BGRA extension - } else { - // oops, we don't handle this format, try the regular path - goto regular; - } - textureWidth = tw; - textureHeight = th; - } else { + regular: - Rect bounds(dirty.bounds()); - GLvoid* data = 0; - if (texture_w!=textureWidth || texture_h!=textureHeight) { - // texture size changed, we need to create a new one - - if (!textureWidth || !textureHeight) { - // this is the first time, load the whole texture - if (texture_w==tw && texture_h==th) { - // we can do it one pass - data = t.data; - } else { - // we have to create the texture first because it - // doesn't match the size of the buffer - bounds.set(Rect(tw, th)); - } - } - - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGB, texture_w, texture_h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexImage2D(GL_TEXTURE_2D, 0, - GL_RGBA, texture_w, texture_h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || - t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { - // just show the Y plane of YUV buffers + Rect bounds(dirty.bounds()); + GLvoid* data = 0; + if (texture_w!=textureWidth || texture_h!=textureHeight) { + // texture size changed, we need to create a new one + + if (!textureWidth || !textureHeight) { + // this is the first time, load the whole texture + if (texture_w==tw && texture_h==th) { + // we can do it one pass data = t.data; - glTexImage2D(GL_TEXTURE_2D, 0, - GL_LUMINANCE, texture_w, texture_h, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); } else { - // oops, we don't handle this format! - LOGE("layer %p, texture=%d, using format %d, which is not " - "supported by the GL", this, textureName, t.format); - textureName = -1; + // we have to create the texture first because it + // doesn't match the size of the buffer + bounds.set(Rect(tw, th)); } - textureWidth = texture_w; - textureHeight = texture_h; } - if (!data && textureName>=0) { - if (t.format == GGL_PIXEL_FORMAT_RGB_565) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, - t.data + bounds.top*t.width*2); - } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { - glTexSubImage2D(GL_TEXTURE_2D, 0, - 0, bounds.top, t.width, bounds.height(), - GL_RGBA, GL_UNSIGNED_BYTE, - t.data + bounds.top*t.width*4); - } + + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGB, texture_w, texture_h, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexImage2D(GL_TEXTURE_2D, 0, + GL_RGBA, texture_w, texture_h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, data); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexImage2D(GL_TEXTURE_2D, 0, + GL_LUMINANCE, texture_w, texture_h, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, data); + } else { + // oops, we don't handle this format! + LOGE("layer %p, texture=%d, using format %d, which is not " + "supported by the GL", this, textureName, t.format); + textureName = -1; + } + textureWidth = texture_w; + textureHeight = texture_h; + } + if (!data && textureName>=0) { + if (t.format == GGL_PIXEL_FORMAT_RGB_565) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_4444) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, + t.data + bounds.top*t.stride*2); + } else if (t.format == GGL_PIXEL_FORMAT_RGBA_8888) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_RGBA, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride*4); + } else if ( t.format == GGL_PIXEL_FORMAT_YCbCr_422_SP || + t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) { + // just show the Y plane of YUV buffers + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, bounds.top, t.width, bounds.height(), + GL_LUMINANCE, GL_UNSIGNED_BYTE, + t.data + bounds.top*t.stride); } } -} - -bool LayerBase::canUseCopybit() const -{ - return mCanUseCopyBit; } // --------------------------------------------------------------------------- @@ -704,9 +645,12 @@ LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ), mIndex(i) { - if (client) { - client->bindLayer(this, i); +} +void LayerBaseClient::onFirstRef() +{ + if (client) { + client->bindLayer(this, mIndex); // Initialize this layer's control block memset(this->lcblk, 0, sizeof(layer_cblk_t)); this->lcblk->identity = mIdentity; @@ -729,11 +673,113 @@ int32_t LayerBaseClient::serverIndex() const { return 0xFFFF0000 | mIndex; } -sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const +sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() +{ + sp<Surface> s; + Mutex::Autolock _l(mLock); + s = mClientSurface.promote(); + if (s == 0) { + s = createSurface(); + mClientSurface = s; + } + return s; +} + +sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const +{ + return new Surface(mFlinger, clientIndex(), mIdentity, + const_cast<LayerBaseClient *>(this)); +} + +// --------------------------------------------------------------------------- + +LayerBaseClient::Surface::Surface( + const sp<SurfaceFlinger>& flinger, + SurfaceID id, int identity, + const sp<LayerBaseClient>& owner) + : mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner) +{ +} + + +LayerBaseClient::Surface::~Surface() +{ + /* + * This is a good place to clean-up all client resources + */ + + // destroy client resources + sp<LayerBaseClient> layer = getOwner(); + if (layer != 0) { + mFlinger->destroySurface(layer); + } +} + +sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const { + sp<LayerBaseClient> owner(mOwner.promote()); + return owner; +} + + +void LayerBaseClient::Surface::getSurfaceData( + ISurfaceFlingerClient::surface_data_t* params) const +{ + params->token = mToken; + params->identity = mIdentity; +} + +status_t LayerBaseClient::Surface::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case REGISTER_BUFFERS: + case UNREGISTER_BUFFERS: + case CREATE_OVERLAY: + { + // codes that require permission check + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int self_pid = getpid(); + if (LIKELY(pid != self_pid)) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.ACCESS_SURFACE_FLINGER"))) + { + const int uid = ipc->getCallingUid(); + LOGE("Permission Denial: " + "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + } + } + return BnSurface::onTransact(code, data, reply, flags); +} + +sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() { - return new Surface(clientIndex(), mIdentity); + return NULL; +} + +status_t LayerBaseClient::Surface::registerBuffers( + const ISurface::BufferHeap& buffers) +{ + return INVALID_OPERATION; } +void LayerBaseClient::Surface::postBuffer(ssize_t offset) +{ +} + +void LayerBaseClient::Surface::unregisterBuffers() +{ +} + +sp<OverlayRef> LayerBaseClient::Surface::createOverlay( + uint32_t w, uint32_t h, int32_t format) +{ + return NULL; +}; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index a020f44..509dedd 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -22,6 +22,8 @@ #include <private/ui/LayerState.h> +#include <utils/RefBase.h> + #include <ui/Region.h> #include <ui/Overlay.h> @@ -37,10 +39,12 @@ class SurfaceFlinger; class DisplayHardware; class GraphicPlane; class Client; +class SurfaceBuffer; +class Buffer; // --------------------------------------------------------------------------- -class LayerBase +class LayerBase : public RefBase { // poor man's dynamic_cast below template<typename T> @@ -69,10 +73,7 @@ public: } - static Vector<GLuint> deletedTextures; - LayerBase(SurfaceFlinger* flinger, DisplayID display); - virtual ~LayerBase(); DisplayID dpy; mutable bool contentDirty; @@ -201,21 +202,29 @@ public: /** * isSecure - true if this surface is secure, that is if it prevents - * screenshots or vns servers. + * screenshots or VNC servers. */ virtual bool isSecure() const { return false; } - enum { // flags for doTransaction() - eVisibleRegion = 0x00000002, - eRestartTransaction = 0x00000008 - }; + /** signal this layer that it's not needed any longer. called from the + * main thread */ + virtual status_t ditch() { return NO_ERROR; } + + + + enum { // flags for doTransaction() + eVisibleRegion = 0x00000002, + eRestartTransaction = 0x00000008 + }; inline const State& drawingState() const { return mDrawingState; } inline const State& currentState() const { return mCurrentState; } inline State& currentState() { return mCurrentState; } - static int compareCurrentStateZ(LayerBase*const* layerA, LayerBase*const* layerB) { + static int compareCurrentStateZ( + sp<LayerBase> const * layerA, + sp<LayerBase> const * layerB) { return layerA[0]->currentState().z - layerB[0]->currentState().z; } @@ -231,7 +240,7 @@ protected: void drawWithOpenGL(const Region& clip, GLint textureName, - const GGLSurface& surface, + const sp<const Buffer>& buffer, int transform = 0) const; void clearWithOpenGL(const Region& clip) const; @@ -240,9 +249,7 @@ protected: GLint textureName, const GGLSurface& t, GLuint& textureWidth, GLuint& textureHeight) const; - bool canUseCopybit() const; - - SurfaceFlinger* mFlinger; + sp<SurfaceFlinger> mFlinger; uint32_t mFlags; // cached during validateVisibility() @@ -250,7 +257,6 @@ protected: int32_t mOrientation; GLfixed mVertices[4][2]; Rect mTransformedBounds; - bool mCanUseCopyBit; int mLeft; int mTop; @@ -269,9 +275,13 @@ protected: volatile int32_t mInvalidate; +protected: + virtual ~LayerBase(); + private: - void validateTexture(GLint textureName) const; - static int32_t sIdentity; + LayerBase(const LayerBase& rhs); + void validateTexture(GLint textureName) const; + static int32_t sIdentity; }; @@ -289,64 +299,58 @@ public: LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, Client* client, int32_t i); virtual ~LayerBaseClient(); - + virtual void onFirstRef(); Client* const client; layer_cblk_t* const lcblk; + inline uint32_t getIdentity() const { return mIdentity; } inline int32_t clientIndex() const { return mIndex; } int32_t serverIndex() const; - virtual sp<Surface> getSurface() const; - uint32_t getIdentity() const { return mIdentity; } + sp<Surface> getSurface(); + virtual sp<Surface> createSurface() const; + class Surface : public BnSurface { public: - Surface(SurfaceID id, int identity) { - mParams.token = id; - mParams.identity = identity; - } - Surface(SurfaceID id, - const sp<IMemoryHeap>& heap0, - const sp<IMemoryHeap>& heap1, - int identity) - { - mParams.token = id; - mParams.identity = identity; - mParams.heap[0] = heap0; - mParams.heap[1] = heap1; - } - virtual ~Surface() { - // TODO: We now have a point here were we can clean-up the - // client's mess. - // This is also where surface id should be recycled. - //LOGD("Surface %d, heaps={%p, %p} destroyed", - // mId, mHeap[0].get(), mHeap[1].get()); - } - + virtual void getSurfaceData( - ISurfaceFlingerClient::surface_data_t* params) const { - *params = mParams; - } - - virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) - { return INVALID_OPERATION; } - virtual void postBuffer(ssize_t offset) { } - virtual void unregisterBuffers() { }; - virtual sp<OverlayRef> createOverlay( - uint32_t w, uint32_t h, int32_t format) { - return NULL; - }; + ISurfaceFlingerClient::surface_data_t* params) const; + + protected: + Surface(const sp<SurfaceFlinger>& flinger, + SurfaceID id, int identity, + const sp<LayerBaseClient>& owner); + virtual ~Surface(); + virtual status_t onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags); + sp<LayerBaseClient> getOwner() const; private: - ISurfaceFlingerClient::surface_data_t mParams; + virtual sp<SurfaceBuffer> getBuffer(); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); + virtual void postBuffer(ssize_t offset); + virtual void unregisterBuffers(); + virtual sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, + int32_t format); + + protected: + friend class LayerBaseClient; + sp<SurfaceFlinger> mFlinger; + int32_t mToken; + int32_t mIdentity; + wp<LayerBaseClient> mOwner; }; -private: - int32_t mIndex; + friend class Surface; +private: + int32_t mIndex; + mutable Mutex mLock; + mutable wp<Surface> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index eb3c3e5..a368ca9 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -14,172 +14,190 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> -#include <cutils/memory.h> #include <utils/Errors.h> #include <utils/Log.h> #include <binder/MemoryDealer.h> +#include <binder/MemoryBase.h> #include <binder/IMemory.h> + #include <ui/PixelFormat.h> +#include <ui/Surface.h> #include <pixelflinger/pixelflinger.h> +#include "BufferAllocator.h" #include "LayerBitmap.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" namespace android { -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== -LayerBitmap::LayerBitmap() - : mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2) +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), + mVStride(0) { - memset(&mSurface, 0, sizeof(mSurface)); + this->format = format; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } } -LayerBitmap::~LayerBitmap() +Buffer::~Buffer() { - mSurface.data = 0; + if (handle) { + BufferAllocator& allocator(BufferAllocator::get()); + allocator.free(handle); + } } -status_t LayerBitmap::init(const sp<MemoryDealer>& allocator) -{ - if (mAllocator != NULL) - return BAD_VALUE; - mAllocator = allocator; - return NO_ERROR; +status_t Buffer::initCheck() const { + return mInitCheck; } -status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags) +android_native_buffer_t* Buffer::getNativeBuffer() const { - const sp<MemoryDealer>& allocator(mAllocator); - if (allocator == NULL) - return NO_INIT; - - if (UNLIKELY(w == mSurface.width && h == mSurface.height && - format == mSurface.format)) - { // same format and size, do nothing. - return NO_ERROR; - } - - PixelFormatInfo info; - getPixelFormatInfo(format, &info); - - uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; - const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = info.bytesPerPixel; - uint32_t stride = (w + (alignment-1)) & ~(alignment-1); - stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = info.getScanlineSize(stride) * h; - if (allocFlags & MemoryDealer::PAGE_ALIGNED) { - size_t pagesize = getpagesize(); - size = (size + (pagesize-1)) & ~(pagesize-1); - } + return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this)); +} - /* FIXME: we should be able to have a h/v stride because the user of the - * surface might have stride limitation (for instance h/w codecs often do) +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + BufferAllocator& allocator = BufferAllocator::get(); + + /* + * buffers used for software rendering, but h/w composition + * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE + * + * buffers used for h/w rendering and h/w composition + * are allocated with HW_RENDER | HW_TEXTURE + * + * buffers used with h/w rendering and either NPOT or no egl_image_ext + * are allocated with SW_READ_RARELY | HW_RENDER + * */ - int32_t vstride = 0; - - mAlignment = alignment; - mAllocFlags = allocFlags; - mOffset = 0; - if (mSize != size) { - // would be nice to have a reallocate() api - mBitsMemory.clear(); // free-memory - mBitsMemory = allocator->allocate(size, allocFlags); - mSize = size; + + if (mFlags & Buffer::SECURE) { + // secure buffer, don't store it into the GPU + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN; } else { - // don't erase memory if we didn't have to reallocate - flags &= ~SECURE_BITS; - } - if (mBitsMemory != 0) { - mOffset = mBitsMemory->offset(); - mSurface.data = static_cast<GGLubyte*>(mBitsMemory->pointer()); - mSurface.version = sizeof(GGLSurface); - mSurface.width = w; - mSurface.height = h; - mSurface.stride = stride; - mSurface.vstride = vstride; - mSurface.format = format; - if (flags & SECURE_BITS) - clear(); + if (mFlags & Buffer::GPU) { + // the client wants to do GL rendering + usage = BufferAllocator::USAGE_HW_RENDER | + BufferAllocator::USAGE_HW_TEXTURE; + } else { + // software rendering-client, h/w composition + usage = BufferAllocator::USAGE_SW_READ_OFTEN | + BufferAllocator::USAGE_SW_WRITE_OFTEN | + BufferAllocator::USAGE_HW_TEXTURE; + } } - if (mBitsMemory==0 || mSurface.data==0) { - LOGE("not enough memory for layer bitmap " - "size=%u (w=%d, h=%d, stride=%d, format=%d)", - size, int(w), int(h), int(stride), int(format)); - allocator->dump("LayerBitmap"); - mSurface.data = 0; - mSize = -1U; - return NO_MEMORY; + err = allocator.alloc(w, h, format, usage, &handle, &stride); + + if (err == NO_ERROR) { + if (err == NO_ERROR) { + width = w; + height = h; + mVStride = 0; + } } - return NO_ERROR; + + return err; } -void LayerBitmap::clear() +status_t Buffer::lock(GGLSurface* sur, uint32_t usage) { - // NOTE: this memset should not be necessary, at least for - // opaque surface. However, for security reasons it's better to keep it - // (in the case of pmem, it's possible that the memory contains old - // data) - if (mSurface.data) { - memset(mSurface.data, 0, mSize); - //if (bytesPerPixel(mSurface.format) == 4) { - // android_memset32((uint32_t*)mSurface.data, 0xFF0000FF, mSize); - //} else { - // android_memset16((uint16_t*)mSurface.data, 0xF800, mSize); - //} + void* vaddr; + status_t res = SurfaceBuffer::lock(usage, &vaddr); + if (res == NO_ERROR && sur) { + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast<GGLubyte*>(vaddr); } + return res; } -status_t LayerBitmap::getInfo(surface_info_t* info) const + + +// =========================================================================== +// LayerBitmap +// =========================================================================== + + +LayerBitmap::LayerBitmap() + : mInfo(0), mWidth(0), mHeight(0) +{ +} + +LayerBitmap::~LayerBitmap() { - if (mSurface.data == 0) { - memset(info, 0, sizeof(surface_info_t)); - info->bits_offset = NO_MEMORY; - return NO_MEMORY; - } - info->w = uint16_t(width()); - info->h = uint16_t(height()); - info->stride= uint16_t(stride()); - info->bpr = uint16_t(stride() * bytesPerPixel(pixelFormat())); - info->format= uint8_t(pixelFormat()); - info->flags = surface_info_t::eBufferDirty; - info->bits_offset = ssize_t(mOffset); - return NO_ERROR; } -status_t LayerBitmap::resize(uint32_t w, uint32_t h) +status_t LayerBitmap::init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS); - return err; + if (info == NULL) + return BAD_VALUE; + + mFormat = format; + mFlags = flags; + mWidth = w; + mHeight = h; + + mInfo = info; + memset(info, 0, sizeof(surface_info_t)); + info->flags = surface_info_t::eNeedNewBuffer; + + // init the buffer, but don't trigger an allocation + mBuffer = new Buffer(0, 0, format, flags); + return NO_ERROR; } -size_t LayerBitmap::size() const +status_t LayerBitmap::setSize(uint32_t w, uint32_t h) { - return mSize; + Mutex::Autolock _l(mLock); + if ((w != mWidth) || (h != mHeight)) { + mWidth = w; + mHeight = h; + // this will signal the client that it needs to asks us for a new buffer + mInfo->flags = surface_info_t::eNeedNewBuffer; + } + return NO_ERROR; } -void LayerBitmap::getBitmapSurface(copybit_image_t* img) const +sp<Buffer> LayerBitmap::allocate() { - const sp<IMemoryHeap>& mh(getAllocator()->getMemoryHeap()); - void* sbase = mh->base(); - const GGLSurface& t(surface()); - img->w = t.stride ?: t.width; - img->h = t.vstride ?: t.height; - img->format = t.format; - img->offset = intptr_t(t.data) - intptr_t(sbase); - img->base = sbase; - img->fd = mh->heapID(); + Mutex::Autolock _l(mLock); + sp<Buffer> buffer(mBuffer); + const uint32_t w = mWidth; + const uint32_t h = mHeight; + if (w != buffer->getWidth() || h != buffer->getHeight()) { + surface_info_t* info = mInfo; + buffer = new Buffer(w, h, mFormat, mFlags); + status_t err = buffer->initCheck(); + if (LIKELY(err == NO_ERROR)) { + info->flags = surface_info_t::eBufferDirty; + info->status = NO_ERROR; + } else { + memset(info, 0, sizeof(surface_info_t)); + info->status = NO_MEMORY; + } + mBuffer = buffer; + } + return buffer; } // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 9ad64c4..824e0f2 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -20,63 +20,114 @@ #include <stdint.h> #include <sys/types.h> +#include <hardware/gralloc.h> + #include <utils/Atomic.h> + #include <ui/PixelFormat.h> #include <ui/Rect.h> -#include <private/ui/SharedState.h> +#include <ui/Surface.h> + #include <pixelflinger/pixelflinger.h> +#include <private/ui/SharedState.h> +#include <private/ui/SurfaceBuffer.h> + class copybit_image_t; +struct android_native_buffer_t; namespace android { // --------------------------------------------------------------------------- - class IMemory; class MemoryDealer; class LayerBitmap; -// --------------------------------------------------------------------------- +// =========================================================================== +// Buffer +// =========================================================================== -class LayerBitmap +class NativeBuffer; + +class Buffer : public SurfaceBuffer { public: - enum { - // erase memory to ensure security when necessary - SECURE_BITS = 0x00000001 + DONT_CLEAR = 0x00000001, + GPU = 0x00000002, + SECURE = 0x00000004 }; - LayerBitmap(); - ~LayerBitmap(); - status_t init(const sp<MemoryDealer>& allocator); + // creates w * h buffer + Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); + + // return status + status_t initCheck() const; + + uint32_t getWidth() const { return width; } + uint32_t getHeight() const { return height; } + uint32_t getStride() const { return stride; } + uint32_t getUsage() const { return usage; } + PixelFormat getPixelFormat() const { return format; } + Rect getBounds() const { return Rect(width, height); } + + status_t lock(GGLSurface* surface, uint32_t usage); + + android_native_buffer_t* getNativeBuffer() const; + +private: + friend class LightRefBase<Buffer>; + Buffer(const Buffer& rhs); + virtual ~Buffer(); + Buffer& operator = (const Buffer& rhs); + const Buffer& operator = (const Buffer& rhs) const; + + status_t initSize(uint32_t w, uint32_t h); + + ssize_t mInitCheck; + uint32_t mFlags; + uint32_t mVStride; +}; + +// =========================================================================== +// LayerBitmap +// =========================================================================== + +class LayerBitmap +{ +public: + enum { + DONT_CLEAR = Buffer::DONT_CLEAR, + GPU = Buffer::GPU, + SECURE = Buffer::SECURE + }; + LayerBitmap(); + ~LayerBitmap(); - status_t setBits(uint32_t w, uint32_t h, uint32_t alignment, - PixelFormat format, uint32_t flags = 0); - void clear(); + status_t init(surface_info_t* info, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0); - status_t getInfo(surface_info_t* info) const; - status_t resize(uint32_t w, uint32_t h); + status_t setSize(uint32_t w, uint32_t h); - const GGLSurface& surface() const { return mSurface; } - Rect bounds() const { return Rect(width(), height()); } - uint32_t width() const { return surface().width; } - uint32_t height() const { return surface().height; } - uint32_t stride() const { return surface().stride; } - PixelFormat pixelFormat() const { return surface().format; } - void* serverBits() const { return surface().data; } - size_t size() const; - const sp<MemoryDealer>& getAllocator() const { return mAllocator; } - void getBitmapSurface(copybit_image_t* img) const; + sp<Buffer> allocate(); + sp<const Buffer> getBuffer() const { return mBuffer; } + sp<Buffer> getBuffer() { return mBuffer; } + + uint32_t getWidth() const { return mWidth; } + uint32_t getHeight() const { return mHeight; } + PixelFormat getPixelFormat() const { return mBuffer->getPixelFormat(); } + Rect getBounds() const { return mBuffer->getBounds(); } + private: - sp<MemoryDealer> mAllocator; - sp<IMemory> mBitsMemory; - uint32_t mAllocFlags; - ssize_t mOffset; - GGLSurface mSurface; - size_t mSize; - uint32_t mAlignment; + surface_info_t* mInfo; + sp<Buffer> mBuffer; + uint32_t mWidth; + uint32_t mHeight; + PixelFormat mFormat; + uint32_t mFlags; + // protects setSize() and allocate() + mutable Mutex mLock; }; }; // namespace android diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index d3e456f..3d22e3a 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> @@ -49,8 +47,7 @@ LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, LayerBlur::~LayerBlur() { if (mTextureName != -1U) { - //glDeleteTextures(1, &mTextureName); - deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } } @@ -139,8 +136,9 @@ void LayerBlur::onDraw(const Region& clip) const glGenTextures(1, &mTextureName); } - Region::iterator iterator(clip); - if (iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (it != end) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTextureName); @@ -201,27 +199,25 @@ void LayerBlur::onDraw(const Region& clip) const glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(2, GL_FIXED, 0, mVertices); glTexCoordPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { + while (it != end) { + const Rect& r = *it++; const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } else { - Region::iterator iterator(clip); - if (iterator) { - // NOTE: this is marginally faster with the software gl, because - // glReadPixels() reads the fb bottom-to-top, however we'll - // skip all the jaccobian computations. - Rect r; - GLint crop[4] = { 0, 0, w, h }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - y = fbHeight - (y + h); - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, w, h); - } + // NOTE: this is marginally faster with the software gl, because + // glReadPixels() reads the fb bottom-to-top, however we'll + // skip all the jaccobian computations. + Rect r; + GLint crop[4] = { 0, 0, w, h }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + y = fbHeight - (y + h); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawTexiOES(x, y, 0, w, h); } } } diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index bac544a..8be91c9 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <math.h> @@ -25,15 +23,10 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> - #include <ui/PixelFormat.h> -#include <ui/EGLDisplaySurface.h> #include "LayerBuffer.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -55,30 +48,23 @@ LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, LayerBuffer::~LayerBuffer() { - sp<SurfaceBuffer> s(getClientSurface()); - if (s != 0) { - s->disown(); - mClientSurface.clear(); - } } -sp<LayerBuffer::SurfaceBuffer> LayerBuffer::getClientSurface() const +void LayerBuffer::onFirstRef() { - Mutex::Autolock _l(mLock); - return mClientSurface.promote(); + mSurface = new SurfaceBuffer(mFlinger, clientIndex(), + const_cast<LayerBuffer *>(this)); } -sp<LayerBaseClient::Surface> LayerBuffer::getSurface() const +sp<LayerBaseClient::Surface> LayerBuffer::createSurface() const { - sp<SurfaceBuffer> s; - Mutex::Autolock _l(mLock); - s = mClientSurface.promote(); - if (s == 0) { - s = new SurfaceBuffer(clientIndex(), - const_cast<LayerBuffer *>(this)); - mClientSurface = s; - } - return s; + return mSurface; +} + +status_t LayerBuffer::ditch() +{ + mSurface.clear(); + return NO_ERROR; } bool LayerBuffer::needsBlending() const { @@ -192,82 +178,49 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() { // LayerBuffer::SurfaceBuffer // ============================================================================ -LayerBuffer::SurfaceBuffer::SurfaceBuffer(SurfaceID id, LayerBuffer* owner) -: LayerBaseClient::Surface(id, owner->getIdentity()), mOwner(owner) +LayerBuffer::SurfaceBuffer::SurfaceBuffer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<LayerBuffer>& owner) + : LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner) { } LayerBuffer::SurfaceBuffer::~SurfaceBuffer() { unregisterBuffers(); - mOwner = 0; -} - -status_t LayerBuffer::SurfaceBuffer::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch (code) { - case REGISTER_BUFFERS: - case UNREGISTER_BUFFERS: - case CREATE_OVERLAY: - { - // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); - if (LIKELY(pid != self_pid)) { - // we're called from a different process, do the real check - if (!checkCallingPermission( - String16("android.permission.ACCESS_SURFACE_FLINGER"))) - { - const int uid = ipc->getCallingUid(); - LOGE("Permission Denial: " - "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); - return PERMISSION_DENIED; - } - } - } - } - return LayerBaseClient::Surface::onTransact(code, data, reply, flags); } -status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers) +status_t LayerBuffer::SurfaceBuffer::registerBuffers( + const ISurface::BufferHeap& buffers) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) return owner->registerBuffers(buffers); return NO_INIT; } void LayerBuffer::SurfaceBuffer::postBuffer(ssize_t offset) { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->postBuffer(offset); } void LayerBuffer::SurfaceBuffer::unregisterBuffers() { - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) owner->unregisterBuffers(); } sp<OverlayRef> LayerBuffer::SurfaceBuffer::createOverlay( uint32_t w, uint32_t h, int32_t format) { sp<OverlayRef> result; - LayerBuffer* owner(getOwner()); - if (owner) + sp<LayerBuffer> owner(getOwner()); + if (owner != 0) result = owner->createOverlay(w, h, format); return result; } -void LayerBuffer::SurfaceBuffer::disown() -{ - Mutex::Autolock _l(mLock); - mOwner = 0; -} - // ============================================================================ // LayerBuffer::Buffer // ============================================================================ @@ -369,7 +322,7 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, LayerBuffer::BufferSource::~BufferSource() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } } @@ -427,125 +380,37 @@ bool LayerBuffer::BufferSource::transformed() const void LayerBuffer::BufferSource::onDraw(const Region& clip) const { - sp<Buffer> buffer(getBuffer()); + // FIXME: we should get a native buffer here + /* + sp<Buffer> ourBbuffer(getBuffer()); if (UNLIKELY(buffer == 0)) { // nothing to do, we don't have a buffer mLayer.clearWithOpenGL(clip); return; } - status_t err = NO_ERROR; - NativeBuffer src(buffer->getBuffer()); - const Rect& transformedBounds = mLayer.getTransformedBounds(); - const int can_use_copybit = mLayer.canUseCopybit(); - - if (can_use_copybit) { - const int src_width = src.crop.r - src.crop.l; - const int src_height = src.crop.b - src.crop.t; - int W = transformedBounds.width(); - int H = transformedBounds.height(); - if (mLayer.getOrientation() & Transform::ROT_90) { - int t(W); W=H; H=t; - } - - /* With LayerBuffer, it is likely that we'll have to rescale the - * surface, because this is often used for video playback or - * camera-preview. Since we want these operation as fast as possible - * we make sure we can use the 2D H/W even if it doesn't support - * the requested scale factor, in which case we perform the scaling - * in several passes. */ - - copybit_device_t* copybit = mLayer.mFlinger->getBlitEngine(); - const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT); - const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT); - - float xscale = 1.0f; - if (src_width > W*min) xscale = 1.0f / min; - else if (src_width*mag < W) xscale = mag; - - float yscale = 1.0f; - if (src_height > H*min) yscale = 1.0f / min; - else if (src_height*mag < H) yscale = mag; - - if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) { - if (UNLIKELY(mTemporaryDealer == 0)) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - mTempBitmap.init(mTemporaryDealer); - } - - const int tmp_w = floorf(src_width * xscale); - const int tmp_h = floorf(src_height * yscale); - err = mTempBitmap.setBits(tmp_w, tmp_h, 1, src.img.format); - - if (LIKELY(err == NO_ERROR)) { - NativeBuffer tmp; - mTempBitmap.getBitmapSurface(&tmp.img); - tmp.crop.l = 0; - tmp.crop.t = 0; - tmp.crop.r = tmp.img.w; - tmp.crop.b = tmp.img.h; - - region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - err = copybit->stretch(copybit, - &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it); - src = tmp; - } - } - - const DisplayHardware& hw(mLayer.graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } - - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - err = copybit->stretch(copybit, - &dst, &src.img, &drect, &src.crop, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } + // FIXME: We should model this after the overlay stuff + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = mLayer.createTexture(); } - if (!can_use_copybit || err) { - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = mLayer.createTexture(); - } + // FIXME: Use EGLImage extension for this + + + + GGLSurface t; + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + if (res == NO_ERROR) { GLuint w = 0; GLuint h = 0; - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - t.stride = src.img.w; - t.vstride= src.img.h; - t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); - const Region dirty(Rect(t.width, t.height)); + const Region dirty(Rect(buffer->width, buffer->height)); mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); + buffer->unlock(); + } + if (res == NO_ERROR) { + mLayer.drawWithOpenGL(clip, mTextureName, buffer, mBufferHeap.transform); } + */ } diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index f74d6a1..22af43e 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -22,7 +22,6 @@ #include <binder/IMemory.h> #include <private/ui/LayerState.h> -#include <EGL/eglnatives.h> #include "LayerBase.h" #include "LayerBitmap.h" @@ -51,7 +50,6 @@ class LayerBuffer : public LayerBaseClient LayerBuffer& mLayer; }; - public: static const uint32_t typeInfo; static const char* const typeID; @@ -62,9 +60,11 @@ public: Client* client, int32_t i); virtual ~LayerBuffer(); + virtual void onFirstRef(); virtual bool needsBlending() const; - virtual sp<LayerBaseClient::Surface> getSurface() const; + virtual sp<LayerBaseClient::Surface> createSurface() const; + virtual status_t ditch(); virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); @@ -126,8 +126,7 @@ private: status_t mStatus; ISurface::BufferHeap mBufferHeap; size_t mBufferSize; - mutable sp<MemoryDealer> mTemporaryDealer; - mutable LayerBitmap mTempBitmap; + mutable sp<android::Buffer> mTempBitmap; mutable GLuint mTextureName; }; @@ -179,34 +178,27 @@ private: class SurfaceBuffer : public LayerBaseClient::Surface { public: - SurfaceBuffer(SurfaceID id, LayerBuffer* owner); + SurfaceBuffer(const sp<SurfaceFlinger>& flinger, + SurfaceID id, const sp<LayerBuffer>& owner); virtual ~SurfaceBuffer(); - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); + virtual sp<OverlayRef> createOverlay( uint32_t w, uint32_t h, int32_t format); - void disown(); private: - LayerBuffer* getOwner() const { - Mutex::Autolock _l(mLock); - return mOwner; + sp<LayerBuffer> getOwner() const { + return static_cast<LayerBuffer*>(Surface::getOwner().get()); } - mutable Mutex mLock; - LayerBuffer* mOwner; }; - - friend class SurfaceFlinger; - sp<SurfaceBuffer> getClientSurface() const; - + mutable Mutex mLock; sp<Source> mSource; - + sp<Surface> mSurface; bool mInvalidate; bool mNeedsBlending; - mutable wp<SurfaceBuffer> mClientSurface; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp index 0c347cc..c1e8ad6 100644 --- a/libs/surfaceflinger/LayerDim.cpp +++ b/libs/surfaceflinger/LayerDim.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdint.h> #include <sys/types.h> @@ -25,7 +23,6 @@ #include "LayerDim.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" namespace android { @@ -33,8 +30,6 @@ namespace android { const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10; const char* const LayerDim::typeID = "LayerDim"; -sp<MemoryDealer> LayerDim::mDimmerDealer; -LayerBitmap LayerDim::mDimmerBitmap; // --------------------------------------------------------------------------- @@ -46,14 +41,6 @@ LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h) { - // must only be called once. - mDimmerDealer = flinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); - if (mDimmerDealer != 0) { - mDimmerBitmap.init(mDimmerDealer); - mDimmerBitmap.setBits(w, h, 1, PIXEL_FORMAT_RGB_565); - mDimmerBitmap.clear(); - } } LayerDim::~LayerDim() @@ -62,48 +49,26 @@ LayerDim::~LayerDim() void LayerDim::onDraw(const Region& clip) const { + // FIXME: on some h/w (like msm7K, it will be faster to use a texture) + const State& s(drawingState()); - - Region::iterator iterator(clip); - if (s.alpha>0 && iterator) { + Region::const_iterator it = clip.begin(); + Region::const_iterator const end = clip.end(); + if (s.alpha>0 && (it != end)) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - status_t err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - // StopWatch watch("copybit"); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds); - - copybit_image_t src; - mDimmerBitmap.getBitmapSurface(&src); - const copybit_rect_t& srect(drect); - - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - region_iterator it(clip); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } - - if (!can_use_copybit || err) { - const GGLfixed alpha = (s.alpha << 16)/255; - const uint32_t fbHeight = hw.getHeight(); - glDisable(GL_TEXTURE_2D); - glDisable(GL_DITHER); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4x(0, 0, 0, alpha); - glVertexPointer(2, GL_FIXED, 0, mVertices); - Rect r; - while (iterator.iterate(&r)) { - const GLint sy = fbHeight - (r.top + r.height()); - glScissor(r.left, sy, r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - } + const GGLfixed alpha = (s.alpha << 16)/255; + const uint32_t fbHeight = hw.getHeight(); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DITHER); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4x(0, 0, 0, alpha); + glVertexPointer(2, GL_FIXED, 0, mVertices); + while (it != end) { + const Rect& r = *it++; + const GLint sy = fbHeight - (r.top + r.height()); + glScissor(r.left, sy, r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } } diff --git a/libs/surfaceflinger/LayerDim.h b/libs/surfaceflinger/LayerDim.h index 3e37a47..0d5bb98 100644 --- a/libs/surfaceflinger/LayerDim.h +++ b/libs/surfaceflinger/LayerDim.h @@ -44,10 +44,6 @@ public: virtual bool isSecure() const { return false; } static void initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h); - -private: - static sp<MemoryDealer> mDimmerDealer; - static LayerBitmap mDimmerBitmap; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp deleted file mode 100644 index fb7b585..0000000 --- a/libs/surfaceflinger/LayerScreenshot.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - -#include "LayerBase.h" -#include "LayerScreenshot.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x20; -const char* const LayerScreenshot::typeID = "LayerScreenshot"; - -// --------------------------------------------------------------------------- - -LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display) - : LayerBase(flinger, display), mReply(0) -{ -} - -LayerScreenshot::~LayerScreenshot() -{ -} - -void LayerScreenshot::onDraw(const Region& clip) const -{ - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - copybit_image_t dst; - hw.getDisplaySurface(&dst); - if (dst.base != 0) { - uint8_t const* src = (uint8_t const*)(intptr_t(dst.base) + dst.offset); - const int fbWidth = dst.w; - const int fbHeight = dst.h; - const int fbFormat = dst.format; - - int x = mTransformedBounds.left; - int y = mTransformedBounds.top; - int w = mTransformedBounds.width(); - int h = mTransformedBounds.height(); - Parcel* const reply = mReply; - if (reply) { - const size_t Bpp = bytesPerPixel(fbFormat); - const size_t size = w * h * Bpp; - int32_t cfg = SkBitmap::kNo_Config; - switch (fbFormat) { - case PIXEL_FORMAT_RGBA_4444: cfg = SkBitmap::kARGB_4444_Config; break; - case PIXEL_FORMAT_RGBA_8888: cfg = SkBitmap::kARGB_8888_Config; break; - case PIXEL_FORMAT_RGB_565: cfg = SkBitmap::kRGB_565_Config; break; - case PIXEL_FORMAT_A_8: cfg = SkBitmap::kA8_Config; break; - } - reply->writeInt32(0); - reply->writeInt32(cfg); - reply->writeInt32(w); - reply->writeInt32(h); - reply->writeInt32(w * Bpp); - void* data = reply->writeInplace(size); - if (data) { - uint8_t* d = (uint8_t*)data; - uint8_t const* s = src + (x + y*fbWidth) * Bpp; - if (w == fbWidth) { - memcpy(d, s, w*h*Bpp); - } else { - for (int y=0 ; y<h ; y++) { - memcpy(d, s, w*Bpp); - d += w*Bpp; - s += fbWidth*Bpp; - } - } - } - } - } - mCV.broadcast(); -} - -void LayerScreenshot::takeScreenshot(Mutex& lock, Parcel* reply) -{ - mReply = reply; - mCV.wait(lock); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/MessageQueue.cpp b/libs/surfaceflinger/MessageQueue.cpp new file mode 100644 index 0000000..a027e2b --- /dev/null +++ b/libs/surfaceflinger/MessageQueue.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> + +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/Log.h> +#include <binder/IPCThreadState.h> + +#include "MessageQueue.h" + +namespace android { + +// --------------------------------------------------------------------------- + +void MessageList::insert(const sp<MessageBase>& node) +{ + LIST::iterator cur(mList.begin()); + LIST::iterator end(mList.end()); + while (cur != end) { + if (*node < **cur) { + mList.insert(cur, node); + return; + } + ++cur; + } + mList.insert(++end, node); +} + +void MessageList::remove(MessageList::LIST::iterator pos) +{ + mList.erase(pos); +} + +// --------------------------------------------------------------------------- + +MessageQueue::MessageQueue() +{ + mInvalidateMessage = new MessageBase(INVALIDATE); +} + +MessageQueue::~MessageQueue() +{ +} + +MessageList::value_type MessageQueue::waitMessage(nsecs_t timeout) +{ + MessageList::value_type result; + + bool again; + do { + const nsecs_t timeoutTime = systemTime() + timeout; + while (true) { + Mutex::Autolock _l(mLock); + nsecs_t now = systemTime(); + nsecs_t nextEventTime = -1; + + // invalidate messages are always handled first + if (mInvalidate) { + mInvalidate = false; + mInvalidateMessage->when = now; + result = mInvalidateMessage; + break; + } + + LIST::iterator cur(mMessages.begin()); + if (cur != mMessages.end()) { + result = *cur; + } + + if (result != 0) { + if (result->when <= now) { + // there is a message to deliver + mMessages.remove(cur); + break; + } + if (timeout>=0 && timeoutTime < now) { + // we timed-out, return a NULL message + result = 0; + break; + } + nextEventTime = result->when; + result = 0; + } + + if (timeout >= 0 && nextEventTime > 0) { + if (nextEventTime > timeoutTime) { + nextEventTime = timeoutTime; + } + } + + if (nextEventTime >= 0) { + //LOGD("nextEventTime = %lld ms", nextEventTime); + if (nextEventTime > 0) { + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock, nextEventTime); + } + } else { + //LOGD("going to wait"); + // we're about to wait, flush the binder command buffer + IPCThreadState::self()->flushCommands(); + mCondition.wait(mLock); + } + } + // here we're not holding the lock anymore + + if (result == 0) + break; + + again = result->handler(); + if (again) { + // the message has been processed. release our reference to it + // without holding the lock. + result = 0; + } + + } while (again); + + return result; +} + +status_t MessageQueue::postMessage( + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) +{ + return queueMessage(message, relTime, flags); +} + +status_t MessageQueue::invalidate() { + Mutex::Autolock _l(mLock); + mInvalidate = true; + mCondition.signal(); + return NO_ERROR; +} + +status_t MessageQueue::queueMessage( + const MessageList::value_type& message, nsecs_t relTime, uint32_t flags) +{ + Mutex::Autolock _l(mLock); + message->when = systemTime() + relTime; + mMessages.insert(message); + + //LOGD("MessageQueue::queueMessage time = %lld ms", message->when); + //dumpLocked(message); + + mCondition.signal(); + return NO_ERROR; +} + +void MessageQueue::dump(const MessageList::value_type& message) +{ + Mutex::Autolock _l(mLock); + dumpLocked(message); +} + +void MessageQueue::dumpLocked(const MessageList::value_type& message) +{ + LIST::const_iterator cur(mMessages.begin()); + LIST::const_iterator end(mMessages.end()); + int c = 0; + while (cur != end) { + const char tick = (*cur == message) ? '>' : ' '; + LOGD("%c %d: msg{.what=%08x, when=%lld}", + tick, c, (*cur)->what, (*cur)->when); + ++cur; + c++; + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/MessageQueue.h b/libs/surfaceflinger/MessageQueue.h new file mode 100644 index 0000000..dc8138d --- /dev/null +++ b/libs/surfaceflinger/MessageQueue.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_MESSAGE_QUEUE_H +#define ANDROID_MESSAGE_QUEUE_H + +#include <stdint.h> +#include <errno.h> +#include <sys/types.h> + +#include <utils/threads.h> +#include <utils/Timers.h> +#include <utils/List.h> + + +namespace android { + +// --------------------------------------------------------------------------- + +class MessageBase; + +class MessageList +{ + List< sp<MessageBase> > mList; + typedef List< sp<MessageBase> > LIST; +public: + typedef sp<MessageBase> value_type; + inline LIST::iterator begin() { return mList.begin(); } + inline LIST::const_iterator begin() const { return mList.begin(); } + inline LIST::iterator end() { return mList.end(); } + inline LIST::const_iterator end() const { return mList.end(); } + inline bool isEmpty() const { return mList.empty(); } + void insert(const sp<MessageBase>& node); + void remove(LIST::iterator pos); +}; + +// ============================================================================ + +class MessageBase : + public LightRefBase<MessageBase> +{ +public: + nsecs_t when; + uint32_t what; + int32_t arg0; + + MessageBase() : when(0), what(0), arg0(0) { } + MessageBase(uint32_t what, int32_t arg0=0) + : when(0), what(what), arg0(arg0) { } + + // return true if message has a handler + virtual bool handler() { return false; } + +protected: + virtual ~MessageBase() { } + +private: + friend class LightRefBase<MessageBase>; +}; + +inline bool operator < (const MessageBase& lhs, const MessageBase& rhs) { + return lhs.when < rhs.when; +} + +// --------------------------------------------------------------------------- + +class MessageQueue +{ + typedef List< sp<MessageBase> > LIST; +public: + + // this is a work-around the multichar constant warning. A macro would + // work too, but would pollute the namespace. + template <int a, int b, int c, int d> + struct WHAT { + static const uint32_t Value = + (uint32_t(a&0xff)<<24)|(uint32_t(b&0xff)<<16)| + (uint32_t(c&0xff)<<8)|uint32_t(d&0xff); + }; + + MessageQueue(); + ~MessageQueue(); + + // pre-defined messages + enum { + INVALIDATE = WHAT<'_','p','d','t'>::Value + }; + + MessageList::value_type waitMessage(nsecs_t timeout = -1); + + status_t postMessage(const MessageList::value_type& message, + nsecs_t reltime=0, uint32_t flags = 0); + + status_t invalidate(); + + void dump(const MessageList::value_type& message); + +private: + status_t queueMessage(const MessageList::value_type& message, + nsecs_t reltime, uint32_t flags); + void dumpLocked(const MessageList::value_type& message); + + Mutex mLock; + Condition mCondition; + MessageList mMessages; + bool mInvalidate; + MessageList::value_type mInvalidateMessage; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif /* ANDROID_MESSAGE_QUEUE_H */ diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index efaf016..70f34a1 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdlib.h> #include <stdio.h> #include <stdint.h> @@ -41,26 +39,20 @@ #include <ui/PixelFormat.h> #include <ui/DisplayInfo.h> -#include <ui/EGLDisplaySurface.h> #include <pixelflinger/pixelflinger.h> #include <GLES/gl.h> #include "clz.h" -#include "CPUGauge.h" +#include "BufferAllocator.h" #include "Layer.h" #include "LayerBlur.h" #include "LayerBuffer.h" #include "LayerDim.h" #include "LayerBitmap.h" -#include "LayerOrientationAnim.h" -#include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" -#include "GPUHardware/GPUHardware.h" - /* ideally AID_GRAPHICS would be in a semi-public header * or there would be a way to map a user/group name to its id @@ -94,30 +86,30 @@ SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs) } ssize_t SurfaceFlinger::LayerVector::indexOf( - LayerBase* key, size_t guess) const + const sp<LayerBase>& key, size_t guess) const { if (guess<size() && lookup.keyAt(guess) == key) return guess; const ssize_t i = lookup.indexOfKey(key); if (i>=0) { const size_t idx = lookup.valueAt(i); - LOG_ASSERT(layers[idx]==key, + LOGE_IF(layers[idx]!=key, "LayerVector[%p]: layers[%d]=%p, key=%p", - this, int(idx), layers[idx], key); + this, int(idx), layers[idx].get(), key.get()); return idx; } return i; } ssize_t SurfaceFlinger::LayerVector::add( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { size_t count = layers.size(); ssize_t l = 0; ssize_t h = count-1; ssize_t mid; - LayerBase* const* a = layers.array(); + sp<LayerBase> const* a = layers.array(); while (l <= h) { mid = l + (h - l)/2; const int c = cmp(a+mid, &layer); @@ -140,14 +132,14 @@ ssize_t SurfaceFlinger::LayerVector::add( return order; } -ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) +ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer) { const ssize_t keyIndex = lookup.indexOfKey(layer); if (keyIndex >= 0) { const size_t index = lookup.valueAt(keyIndex); - LOG_ASSERT(layers[index]==layer, + LOGE_IF(layers[index]!=layer, "LayerVector[%p]: layers[%u]=%p, layer=%p", - this, int(index), layers[index], layer); + this, int(index), layers[index].get(), layer.get()); layers.removeItemsAt(index); lookup.removeItemsAt(keyIndex); const size_t count = lookup.size(); @@ -162,8 +154,8 @@ ssize_t SurfaceFlinger::LayerVector::remove(LayerBase* layer) } ssize_t SurfaceFlinger::LayerVector::reorder( - LayerBase* layer, - Vector<LayerBase*>::compar_t cmp) + const sp<LayerBase>& layer, + Vector< sp<LayerBase> >::compar_t cmp) { // XXX: it's a little lame. but oh well... ssize_t err = remove(layer); @@ -181,6 +173,7 @@ SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionCount(0), + mLayersRemoved(false), mBootTime(systemTime()), mLastScheduledBroadcast(NULL), mVisibleRegionsDirty(false), @@ -189,11 +182,7 @@ SurfaceFlinger::SurfaceFlinger() mFreezeCount(0), mFreezeDisplayTime(0), mDebugRegion(0), - mDebugCpu(0), - mDebugFps(0), mDebugBackground(0), - mSyncObject(), - mDeplayedTransactionPending(0), mConsoleSignals(0), mSecureFrameBuffer(0) { @@ -208,28 +197,16 @@ void SurfaceFlinger::init() char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); - property_get("debug.sf.showcpu", value, "0"); - mDebugCpu = atoi(value); property_get("debug.sf.showbackground", value, "0"); mDebugBackground = atoi(value); - property_get("debug.sf.showfps", value, "0"); - mDebugFps = atoi(value); LOGI_IF(mDebugRegion, "showupdates enabled"); - LOGI_IF(mDebugCpu, "showcpu enabled"); LOGI_IF(mDebugBackground, "showbackground enabled"); - LOGI_IF(mDebugFps, "showfps enabled"); } SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); - delete mOrientationAnimation; -} - -copybit_device_t* SurfaceFlinger::getBlitEngine() const -{ - return graphicPlane(0).displayHardware().getBlitEngine(); } overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const @@ -242,26 +219,6 @@ sp<IMemory> SurfaceFlinger::getCblk() const return mServerCblkMemory; } -status_t SurfaceFlinger::requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu) -{ - if (mGPU == 0) - return INVALID_OPERATION; - - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - status_t err = mGPU->request(pid, callback, gpu); - return err; -} - -status_t SurfaceFlinger::revokeGPU() -{ - if (mGPU == 0) - return INVALID_OPERATION; - - return mGPU->friendlyRevoke(); -} - sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection() { Mutex::Autolock _l(mStateLock); @@ -289,11 +246,13 @@ void SurfaceFlinger::destroyConnection(ClientID cid) Client* const client = mClientsMap.valueFor(cid); if (client) { // free all the layers this client owns - const Vector<LayerBaseClient*>& layers = client->getLayers(); + const Vector< wp<LayerBaseClient> >& layers = client->getLayers(); const size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - LayerBaseClient* const layer = layers[i]; - removeLayer_l(layer); + sp<LayerBaseClient> layer(layers[i].promote()); + if (layer != 0) { + removeLayer_l(layer); + } } // the resources associated with this client will be freed @@ -345,9 +304,6 @@ static inline uint16_t pack565(int r, int g, int b) { return (r<<11)|(g<<5)|b; } -// this is defined in libGLES_CM.so -extern ISurfaceComposer* GLES_localSurfaceManager; - status_t SurfaceFlinger::readyToRun() { LOGI( "SurfaceFlinger's main thread ready to run. " @@ -364,17 +320,6 @@ status_t SurfaceFlinger::readyToRun() LOGE_IF(mServerCblk==0, "can't get to shared control block's address"); new(mServerCblk) surface_flinger_cblk_t; - // get a reference to the GPU if we have one - mGPU = GPUFactory::getGPU(); - - // create the surface Heap manager, which manages the heaps - // (be it in RAM or VRAM) where surfaces are allocated - // We give 8 MB per client. - mSurfaceHeapManager = new SurfaceHeapManager(this, 8 << 20); - - - GLES_localSurfaceManager = static_cast<ISurfaceComposer*>(this); - // we only support one display currently int dpy = 0; @@ -451,13 +396,6 @@ status_t SurfaceFlinger::readyToRun() * We're now ready to accept clients... */ - mOrientationAnimation = new OrientationAnimation(this); - - // start CPU gauge display - if (mDebugCpu) - mCpuGauge = new CPUGauge(this, ms2ns(500)); - - // start boot animation property_set("ctl.start", "bootanim"); @@ -472,45 +410,53 @@ status_t SurfaceFlinger::readyToRun() void SurfaceFlinger::waitForEvent() { - // wait for something to do - if (UNLIKELY(isFrozen())) { - // wait 5 seconds - const nsecs_t freezeDisplayTimeout = ms2ns(5000); - const nsecs_t now = systemTime(); - if (mFreezeDisplayTime == 0) { - mFreezeDisplayTime = now; + while (true) { + nsecs_t timeout = -1; + if (UNLIKELY(isFrozen())) { + // wait 5 seconds + const nsecs_t freezeDisplayTimeout = ms2ns(5000); + const nsecs_t now = systemTime(); + if (mFreezeDisplayTime == 0) { + mFreezeDisplayTime = now; + } + nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); + timeout = waitTime>0 ? waitTime : 0; } - nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); - int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT; - if (err != NO_ERROR) { + + MessageList::value_type msg = mEventQueue.waitMessage(timeout); + if (msg != 0) { + mFreezeDisplayTime = 0; + switch (msg->what) { + case MessageQueue::INVALIDATE: + // invalidate message, just return to the main loop + return; + } + } else { + // we timed out if (isFrozen()) { // we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeCount = 0; mFreezeDisplay = false; + return; } } - } else { - mFreezeDisplayTime = 0; - mSyncObject.wait(); } } void SurfaceFlinger::signalEvent() { - mSyncObject.open(); + mEventQueue.invalidate(); } void SurfaceFlinger::signal() const { - mSyncObject.open(); + // this is the IPC call + const_cast<SurfaceFlinger*>(this)->signalEvent(); } void SurfaceFlinger::signalDelayedEvent(nsecs_t delay) { - if (android_atomic_or(1, &mDeplayedTransactionPending) == 0) { - sp<DelayedTransaction> delayedEvent(new DelayedTransaction(this, delay)); - delayedEvent->run("DelayedeEvent", PRIORITY_URGENT_DISPLAY); - } + mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay); } // ---------------------------------------------------------------------------- @@ -549,11 +495,6 @@ bool SurfaceFlinger::threadLoop() unlockClients(); executeScheduledBroadcasts(); - // sample the cpu gauge - if (UNLIKELY(mDebugCpu)) { - handleDebugCpu(); - } - postFramebuffer(); } else { // pretend we did the post @@ -566,28 +507,18 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - const bool skip = mOrientationAnimation->run(); - if (UNLIKELY(skip)) { + if (isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps return; } if (!mInvalidRegion.isEmpty()) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - - if (UNLIKELY(mDebugFps)) { - debugShowFPS(); - } - hw.flip(mInvalidRegion); - mInvalidRegion.clear(); - - if (Layer::deletedTextures.size()) { - glDeleteTextures( - Layer::deletedTextures.size(), - Layer::deletedTextures.array()); - Layer::deletedTextures.clear(); - } } } @@ -602,15 +533,13 @@ void SurfaceFlinger::handleConsoleEvents() } if (mDeferReleaseConsole && hw.canDraw()) { - // We got the release signal before the aquire signal + // We got the release signal before the acquire signal mDeferReleaseConsole = false; - revokeGPU(); hw.releaseScreen(); } if (what & eConsoleReleased) { if (hw.canDraw()) { - revokeGPU(); hw.releaseScreen(); } else { mDeferReleaseConsole = true; @@ -635,7 +564,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) const bool layersNeedTransaction = transactionFlags & eTraversalNeeded; if (layersNeedTransaction) { for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -682,7 +611,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); mFreezeDisplayTime = 0; - mOrientationAnimation->onOrientationChanged(type); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { @@ -690,17 +618,26 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mFreezeDisplay = mCurrentState.freezeDisplay; } - // some layers might have been removed, so - // we need to update the regions they're exposing. - size_t c = mRemovedLayers.size(); - if (c) { + if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { + // layers have been added mVisibleRegionsDirty = true; } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) { - // layers have been added + // some layers might have been removed, so + // we need to update the regions they're exposing. + if (mLayersRemoved) { mVisibleRegionsDirty = true; + const LayerVector& previousLayers(mDrawingState.layersSortedByZ); + const ssize_t count = previousLayers.size(); + for (ssize_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(previousLayers[i]); + if (currentLayers.indexOf( layer ) < 0) { + // this layer is not visible anymore + // FIXME: would be better to call without the lock held + //LOGD("ditching layer %p", layer.get()); + layer->ditch(); + } + } } // get rid of all resources we don't need anymore @@ -730,7 +667,7 @@ void SurfaceFlinger::computeVisibleRegions( size_t i = currentLayers.size(); while (i--) { - LayerBase* const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; layer->validateVisibility(planeTransform); // start with the whole surface at its current location @@ -782,7 +719,7 @@ void SurfaceFlinger::computeVisibleRegions( // accumulate to the screen dirty region dirtyRegion.orSelf(dirty); - // updade aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer + // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); aboveCoveredLayers.orSelf(bounds); @@ -790,7 +727,7 @@ void SurfaceFlinger::computeVisibleRegions( layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); - // If a secure layer is partially visible, lockdown the screen! + // If a secure layer is partially visible, lock down the screen! if (layer->isSecure() && !visibleRegion.isEmpty()) { secureFrameBuffer = true; } @@ -830,9 +767,9 @@ bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers) { bool recomputeVisibleRegions = false; size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->lockPageFlip(recomputeVisibleRegions); } return recomputeVisibleRegions; @@ -843,9 +780,9 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers) const GraphicPlane& plane(graphicPlane(0)); const Transform& planeTransform(plane.transform()); size_t count = currentLayers.size(); - LayerBase* const* layers = currentLayers.array(); + sp<LayerBase> const* layers = currentLayers.array(); for (size_t i=0 ; i<count ; i++) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->unlockPageFlip(planeTransform, mDirtyRegion); } } @@ -865,12 +802,14 @@ void SurfaceFlinger::handleRepaint() mInvalidRegion.orSelf(mDirtyRegion); uint32_t flags = hw.getFlags(); - if (flags & DisplayHardware::BUFFER_PRESERVED) { - // here we assume DisplayHardware::flip()'s implementation - // performs the copy-back optimization. + if ((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED)) + { + // we can redraw only what's dirty } else { if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated + // we need to redraw the rectangle that will be updated + // (pushed to the framebuffer). mDirtyRegion.set(mInvalidRegion.bounds()); } else { // we need to redraw everything @@ -896,9 +835,9 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) const SurfaceFlinger& flinger(*this); const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase const* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase const * const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; const Region& visibleRegion(layer->visibleRegionScreen); if (!visibleRegion.isEmpty()) { const Region clip(dirty.intersect(visibleRegion)); @@ -913,9 +852,9 @@ void SurfaceFlinger::unlockClients() { const LayerVector& drawingLayers(mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); - LayerBase* const* const layers = drawingLayers.array(); + sp<LayerBase> const* const layers = drawingLayers.array(); for (size_t i=0 ; i<count ; ++i) { - LayerBase* const layer = layers[i]; + const sp<LayerBase>& layer = layers[i]; layer->finishPageFlip(); } } @@ -948,32 +887,35 @@ void SurfaceFlinger::executeScheduledBroadcasts() mLastScheduledBroadcast = 0; } -void SurfaceFlinger::handleDebugCpu() -{ - Mutex::Autolock _l(mDebugLock); - if (mCpuGauge != 0) - mCpuGauge->sample(); -} - void SurfaceFlinger::debugFlashRegions() { - if (UNLIKELY(!mDirtyRegion.isRect())) { - // TODO: do this only if we don't have preserving - // swapBuffer. If we don't have update-on-demand, - // redraw everything. - composeSurfaces(Region(mDirtyRegion.bounds())); - } + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const uint32_t flags = hw.getFlags(); + if (!((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED))) { + const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ? + mDirtyRegion.bounds() : hw.bounds()); + composeSurfaces(repaint); + } + glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); - glColor4x(0x10000, 0, 0x10000, 0x10000); + static int toggle = 0; + toggle = 1 - toggle; + if (toggle) { + glColor4x(0x10000, 0, 0x10000, 0x10000); + } else { + glColor4x(0x10000, 0x10000, 0, 0x10000); + } - Rect r; - Region::iterator iterator(mDirtyRegion); - while (iterator.iterate(&r)) { + Region::const_iterator it = mDirtyRegion.begin(); + Region::const_iterator const end = mDirtyRegion.end(); + while (it != end) { + const Rect& r = *it++; GLfloat vertices[][2] = { { r.left, r.top }, { r.left, r.bottom }, @@ -983,8 +925,7 @@ void SurfaceFlinger::debugFlashRegions() glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.flip(mDirtyRegion.merge(mInvalidRegion)); mInvalidRegion.clear(); @@ -1010,9 +951,10 @@ void SurfaceFlinger::drawWormhole() const if (LIKELY(!mDebugBackground)) { glClearColorx(0,0,0,0); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { + Region::const_iterator it = region.begin(); + Region::const_iterator const end = region.end(); + while (it != end) { + const Rect& r = *it++; const GLint sy = height - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glClear(GL_COLOR_BUFFER_BIT); @@ -1030,9 +972,10 @@ void SurfaceFlinger::drawWormhole() const glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1); - Rect r; - Region::iterator iterator(region); - while (iterator.iterate(&r)) { + Region::const_iterator it = region.begin(); + Region::const_iterator const end = region.end(); + while (it != end) { + const Rect& r = *it++; const GLint sy = height - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -1058,7 +1001,7 @@ void SurfaceFlinger::debugShowFPS() const // XXX: mFPS has the value we want } -status_t SurfaceFlinger::addLayer(LayerBase* layer) +status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); addLayer_l(layer); @@ -1066,7 +1009,7 @@ status_t SurfaceFlinger::addLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(LayerBase* layer) +status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) { Mutex::Autolock _l(mStateLock); removeLayer_l(layer); @@ -1074,48 +1017,60 @@ status_t SurfaceFlinger::removeLayer(LayerBase* layer) return NO_ERROR; } -status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) +status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer) { layer->forceVisibilityTransaction(); setTransactionFlags(eTraversalNeeded); return NO_ERROR; } -status_t SurfaceFlinger::addLayer_l(LayerBase* layer) +status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer) { ssize_t i = mCurrentState.layersSortedByZ.add( layer, &LayerBase::compareCurrentStateZ); - LayerBaseClient* lbc = LayerBase::dynamicCast<LayerBaseClient*>(layer); - if (lbc) { + sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { mLayerMap.add(lbc->serverIndex(), lbc); } - mRemovedLayers.remove(layer); return NO_ERROR; } -status_t SurfaceFlinger::removeLayer_l(LayerBase* layerBase) +status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) { ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); if (index >= 0) { - mRemovedLayers.add(layerBase); - LayerBaseClient* layer = LayerBase::dynamicCast<LayerBaseClient*>(layerBase); - if (layer) { + mLayersRemoved = true; + sp<LayerBaseClient> layer = + LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get()); + if (layer != 0) { mLayerMap.removeItem(layer->serverIndex()); } return NO_ERROR; } // it's possible that we don't find a layer, because it might // have been destroyed already -- this is not technically an error - // from the user because there is a race between destroySurface, - // destroyclient and destroySurface-from-a-transaction. + // from the user because there is a race between BClient::destroySurface(), + // ~BClient() and destroySurface-from-a-transaction. return (index == NAME_NOT_FOUND) ? status_t(NO_ERROR) : index; } +status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase) +{ + // First add the layer to the purgatory list, which makes sure it won't + // go away, then remove it from the main list (through a transaction). + ssize_t err = removeLayer_l(layerBase); + if (err >= 0) { + mLayerPurgatory.add(layerBase); + } + return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err; +} + + void SurfaceFlinger::free_resources_l() { // Destroy layers that were removed - destroy_all_removed_layers_l(); - + mLayersRemoved = false; + // free resources associated with disconnected clients SortedVector<Client*>& scheduledBroadcasts(mScheduledBroadcasts); Vector<Client*>& disconnectedClients(mDisconnectedClients); @@ -1135,22 +1090,6 @@ void SurfaceFlinger::free_resources_l() disconnectedClients.clear(); } -void SurfaceFlinger::destroy_all_removed_layers_l() -{ - size_t c = mRemovedLayers.size(); - while (c--) { - LayerBase* const removed_layer = mRemovedLayers[c]; - - LOGE_IF(mCurrentState.layersSortedByZ.indexOf(removed_layer) >= 0, - "layer %p removed but still in the current state list", - removed_layer); - - delete removed_layer; - } - mRemovedLayers.clear(); -} - - uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) { return android_atomic_and(~flags, &mTransactionFlags) & flags; @@ -1191,7 +1130,7 @@ status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags) setTransactionFlags(eTransactionNeeded); // flags is intended to communicate some sort of animation behavior - // (for instance fadding) + // (for instance fading) return NO_ERROR; } @@ -1205,7 +1144,7 @@ status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags) setTransactionFlags(eTransactionNeeded); // flags is intended to communicate some sort of animation behavior - // (for instance fadding) + // (for instance fading) return NO_ERROR; } @@ -1234,7 +1173,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, DisplayID d, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - LayerBaseClient* layer = 0; + sp<LayerBaseClient> layer; sp<LayerBaseClient::Surface> surfaceHandle; Mutex::Autolock _l(mStateLock); Client* const c = mClientsMap.valueFor(clientId); @@ -1266,7 +1205,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, break; } - if (layer) { + if (layer != 0) { setTransactionFlags(eTransactionNeeded); surfaceHandle = layer->getSurface(); if (surfaceHandle != 0) @@ -1276,7 +1215,7 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, return surfaceHandle; } -LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { @@ -1291,57 +1230,92 @@ LayerBaseClient* SurfaceFlinger::createNormalSurfaceLocked( break; } - Layer* layer = new Layer(this, display, client, id); + sp<Layer> layer = new Layer(this, display, client, id); status_t err = layer->setBuffers(client, w, h, format, flags); if (LIKELY(err == NO_ERROR)) { layer->initStates(w, h, flags); addLayer_l(layer); } else { LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); - delete layer; - return 0; + layer.clear(); } return layer; } -LayerBaseClient* SurfaceFlinger::createBlurSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBlur* layer = new LayerBlur(this, display, client, id); + sp<LayerBlur> layer = new LayerBlur(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createDimSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerDim* layer = new LayerDim(this, display, client, id); + sp<LayerDim> layer = new LayerDim(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -LayerBaseClient* SurfaceFlinger::createPushBuffersSurfaceLocked( +sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked( Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags) { - LayerBuffer* layer = new LayerBuffer(this, display, client, id); + sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id); layer->initStates(w, h, flags); addLayer_l(layer); return layer; } -status_t SurfaceFlinger::destroySurface(SurfaceID index) +status_t SurfaceFlinger::removeSurface(SurfaceID index) { + /* + * called by the window manager, when a surface should be marked for + * destruction. + * + * The surface is removed from the current and drawing lists, but placed + * in the purgatory queue, so it's not destroyed right-away (we need + * to wait for all client's references to go away first). + */ + Mutex::Autolock _l(mStateLock); - LayerBaseClient* const layer = getLayerUser_l(index); - status_t err = removeLayer_l(layer); - if (err < 0) - return err; - setTransactionFlags(eTransactionNeeded); + sp<LayerBaseClient> layer = getLayerUser_l(index); + status_t err = purgatorizeLayer_l(layer); + if (err == NO_ERROR) { + setTransactionFlags(eTransactionNeeded); + } + return err; +} + +status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer) +{ + /* + * called by ~ISurface() when all references are gone + * + * the surface must be removed from purgatory from the main thread + * since its dtor must run from there (b/c of OpenGL ES). + */ + + class MessageDestroySurface : public MessageBase { + SurfaceFlinger* flinger; + sp<LayerBaseClient> layer; + public: + MessageDestroySurface( + SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer) + : flinger(flinger), layer(layer) { } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + ssize_t idx = flinger->mLayerPurgatory.remove(layer); + LOGE_IF(idx<0, "layer=%p is not in the purgatory list", layer.get()); + return true; + } + }; + mEventQueue.postMessage( new MessageDestroySurface(this, layer) ); return NO_ERROR; } @@ -1355,8 +1329,8 @@ status_t SurfaceFlinger::setClientState( cid <<= 16; for (int i=0 ; i<count ; i++) { const layer_state_t& s = states[i]; - LayerBaseClient* layer = getLayerUser_l(s.surface | cid); - if (layer) { + const sp<LayerBaseClient>& layer = getLayerUser_l(s.surface | cid); + if (layer != 0) { const uint32_t what = s.what; // check if it has been destroyed first if (what & eDestroyed) { @@ -1408,9 +1382,10 @@ status_t SurfaceFlinger::setClientState( return NO_ERROR; } -LayerBaseClient* SurfaceFlinger::getLayerUser_l(SurfaceID s) const +sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const { - return mLayerMap.valueFor(s); + sp<LayerBaseClient> layer = mLayerMap.valueFor(s); + return layer; } void SurfaceFlinger::screenReleased(int dpy) @@ -1453,7 +1428,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { /*** LayerBase ***/ - LayerBase const * const layer = currentLayers[i]; + const sp<LayerBase>& layer = currentLayers[i]; const Layer::State& s = layer->drawingState(); snprintf(buffer, SIZE, "+ %s %p\n" @@ -1461,7 +1436,7 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), " "needsBlending=%1d, invalidate=%1d, " "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n", - layer->getTypeID(), layer, + layer->getTypeID(), layer.get(), s.z, layer->tx(), layer->ty(), s.w, s.h, layer->needsBlending(), layer->contentDirty, s.alpha, s.flags, @@ -1470,9 +1445,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** LayerBaseClient ***/ - LayerBaseClient* const lbc = - LayerBase::dynamicCast<LayerBaseClient*>((LayerBase*)layer); - if (lbc) { + sp<LayerBaseClient> lbc = + LayerBase::dynamicCast< LayerBaseClient* >(layer.get()); + if (lbc != 0) { snprintf(buffer, SIZE, " " "id=0x%08x, client=0x%08x, identity=%u\n", @@ -1482,18 +1457,20 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) result.append(buffer); buffer[0] = 0; /*** Layer ***/ - Layer* const l = LayerBase::dynamicCast<Layer*>((LayerBase*)layer); - if (l) { + sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get()); + if (l != 0) { const LayerBitmap& buf0(l->getBuffer(0)); const LayerBitmap& buf1(l->getBuffer(1)); snprintf(buffer, SIZE, " " - "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u], mTextureName=%d," + "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u]," " freezeLock=%p, swapState=0x%08x\n", l->pixelFormat(), - buf0.width(), buf0.height(), buf0.stride(), - buf1.width(), buf1.height(), buf1.stride(), - l->getTextureName(), l->getFreezeLock().get(), + buf0.getWidth(), buf0.getHeight(), + buf0.getBuffer()->getStride(), + buf1.getWidth(), buf1.getHeight(), + buf1.getBuffer()->getStride(), + l->getFreezeLock().get(), l->lcblk->swapState); } result.append(buffer); @@ -1510,19 +1487,8 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) mCurrentState.orientation, hw.canDraw()); result.append(buffer); - sp<AllocatorInterface> allocator; - if (mGPU != 0) { - snprintf(buffer, SIZE, " GPU owner: %d\n", mGPU->getOwner()); - result.append(buffer); - allocator = mGPU->getAllocator(); - if (allocator != 0) { - allocator->dump(result, "GPU Allocator"); - } - } - allocator = mSurfaceHeapManager->getAllocator(NATIVE_MEMORY_TYPE_PMEM); - if (allocator != 0) { - allocator->dump(result, "PMEM Allocator"); - } + const BufferAllocator& alloc(BufferAllocator::get()); + alloc.dump(result); } write(fd, result.string(), result.size()); return NO_ERROR; @@ -1539,7 +1505,6 @@ status_t SurfaceFlinger::onTransact( case FREEZE_DISPLAY: case UNFREEZE_DISPLAY: case BOOT_FINISHED: - case REVOKE_GPU: { // codes that require permission check IPCThreadState* ipc = IPCThreadState::self(); @@ -1572,24 +1537,9 @@ status_t SurfaceFlinger::onTransact( } int n; switch (code) { - case 1000: // SHOW_CPU - n = data.readInt32(); - mDebugCpu = n ? 1 : 0; - if (mDebugCpu) { - if (mCpuGauge == 0) { - mCpuGauge = new CPUGauge(this, ms2ns(500)); - } - } else { - if (mCpuGauge != 0) { - mCpuGauge->requestExitAndWait(); - Mutex::Autolock _l(mDebugLock); - mCpuGauge.clear(); - } - } + case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE return NO_ERROR; - case 1001: // SHOW_FPS - n = data.readInt32(); - mDebugFps = n ? 1 : 0; + case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE return NO_ERROR; case 1002: // SHOW_UPDATES n = data.readInt32(); @@ -1606,21 +1556,11 @@ status_t SurfaceFlinger::onTransact( signalEvent(); } return NO_ERROR; - case 1005: // ask GPU revoke - if (mGPU != 0) { - mGPU->friendlyRevoke(); - } - return NO_ERROR; - case 1006: // revoke GPU - if (mGPU != 0) { - mGPU->unconditionalRevoke(); - } - return NO_ERROR; case 1007: // set mFreezeCount mFreezeCount = data.readInt32(); return NO_ERROR; case 1010: // interrogate. - reply->writeInt32(mDebugCpu); + reply->writeInt32(0); reply->writeInt32(0); reply->writeInt32(mDebugRegion); reply->writeInt32(mDebugBackground); @@ -1644,7 +1584,6 @@ status_t SurfaceFlinger::onTransact( Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) { - mSharedHeapAllocator = getSurfaceHeapManager()->createHeap(); const int pgsize = getpagesize(); const int cblksize=((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1)); mCblkHeap = new MemoryDealer(cblksize); @@ -1664,10 +1603,6 @@ Client::~Client() { } } -const sp<SurfaceHeapManager>& Client::getSurfaceHeapManager() const { - return mFlinger->getSurfaceHeapManager(); -} - int32_t Client::generateId(int pid) { const uint32_t i = clz( ~mBitmap ); @@ -1679,13 +1614,15 @@ int32_t Client::generateId(int pid) mBitmap |= 1<<(31-i); return i; } -status_t Client::bindLayer(LayerBaseClient* layer, int32_t id) + +status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id) { ssize_t idx = mInUse.indexOf(id); if (idx < 0) return NAME_NOT_FOUND; return mLayers.insertAt(layer, idx); } + void Client::free(int32_t id) { ssize_t idx = mInUse.remove(uint8_t(id)); @@ -1695,27 +1632,18 @@ void Client::free(int32_t id) } } -sp<MemoryDealer> Client::createAllocator(uint32_t flags) -{ - sp<MemoryDealer> allocator; - allocator = getSurfaceHeapManager()->createHeap( - flags, getClientPid(), mSharedHeapAllocator); - return allocator; -} - bool Client::isValid(int32_t i) const { return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i))); } -const uint8_t* Client::inUseArray() const { - return mInUse.array(); -} -size_t Client::numActiveLayers() const { - return mInUse.size(); -} -LayerBaseClient* Client::getLayerUser(int32_t i) const { + +sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { + sp<LayerBaseClient> lbc; ssize_t idx = mInUse.indexOf(uint8_t(i)); - if (idx<0) return 0; - return mLayers[idx]; + if (idx >= 0) { + lbc = mLayers[idx].promote(); + LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx)); + } + return lbc; } void Client::dump(const char* what) @@ -1752,7 +1680,7 @@ sp<ISurface> BClient::createSurface( status_t BClient::destroySurface(SurfaceID sid) { sid |= (mId << 16); // add the client-part to id - return mFlinger->destroySurface(sid); + return mFlinger->removeSurface(sid); } status_t BClient::setState(int32_t count, const layer_state_t* states) @@ -1852,6 +1780,10 @@ const Transform& GraphicPlane::transform() const { return mGlobalTransform; } +EGLDisplay GraphicPlane::getEGLDisplay() const { + return mHw->getEGLDisplay(); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 126bce8..6bbb21f 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -26,6 +26,7 @@ #include <utils/Atomic.h> #include <utils/Errors.h> #include <binder/MemoryDealer.h> +#include <utils/RefBase.h> #include <ui/PixelFormat.h> #include <ui/ISurfaceComposer.h> @@ -33,13 +34,13 @@ #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> -#include <private/ui/SurfaceFlingerSynchro.h> #include "Barrier.h" -#include "CPUGauge.h" #include "Layer.h" #include "Tokenizer.h" +#include "MessageQueue.h" + struct copybit_device_t; struct overlay_device_t; @@ -51,13 +52,8 @@ class Client; class BClient; class DisplayHardware; class FreezeLock; -class GPUHardwareInterface; -class IGPUCallback; class Layer; class LayerBuffer; -class LayerOrientationAnim; -class OrientationAnimation; -class SurfaceHeapManager; typedef int32_t ClientID; @@ -74,17 +70,13 @@ public: int32_t generateId(int pid); void free(int32_t id); - status_t bindLayer(LayerBaseClient* layer, int32_t id); - sp<MemoryDealer> createAllocator(uint32_t memory_type); + status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id); inline bool isValid(int32_t i) const; - inline const uint8_t* inUseArray() const; - inline size_t numActiveLayers() const; - LayerBaseClient* getLayerUser(int32_t i) const; - const Vector<LayerBaseClient*>& getLayers() const { return mLayers; } + sp<LayerBaseClient> getLayerUser(int32_t i) const; + const Vector< wp<LayerBaseClient> >& getLayers() const { return mLayers; } const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; } void dump(const char* what); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const; // pointer to this client's control block per_client_cblk_t* ctrlblk; @@ -94,15 +86,13 @@ public: private: int getClientPid() const { return mPid; } - int mPid; - uint32_t mBitmap; - SortedVector<uint8_t> mInUse; - Vector<LayerBaseClient*> mLayers; - sp<MemoryDealer> mCblkHeap; - sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mSharedHeapAllocator; - sp<MemoryDealer> mPMemAllocator; - sp<IMemory> mCblkMemory; + int mPid; + uint32_t mBitmap; + SortedVector<uint8_t> mInUse; + Vector< wp<LayerBaseClient> > mLayers; + sp<MemoryDealer> mCblkHeap; + sp<SurfaceFlinger> mFlinger; + sp<IMemory> mCblkMemory; }; // --------------------------------------------------------------------------- @@ -125,6 +115,8 @@ public: const DisplayHardware& displayHardware() const; const Transform& transform() const; + EGLDisplay getEGLDisplay() const; + private: GraphicPlane(const GraphicPlane&); GraphicPlane operator = (const GraphicPlane&); @@ -168,28 +160,16 @@ public: virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags); virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags); virtual void signal() const; - virtual status_t requestGPU(const sp<IGPUCallback>& callback, - gpu_info_t* gpu); - virtual status_t revokeGPU(); void screenReleased(DisplayID dpy); void screenAcquired(DisplayID dpy); - const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { - return mSurfaceHeapManager; - } - - const sp<GPUHardwareInterface>& getGPU() const { - return mGPU; - } - - copybit_device_t* getBlitEngine() const; overlay_control_device_t* getOverlayEngine() const; - status_t removeLayer(LayerBase* layer); - status_t addLayer(LayerBase* layer); - status_t invalidateLayerVisibility(LayerBase* layer); + status_t removeLayer(const sp<LayerBase>& layer); + status_t addLayer(const sp<LayerBase>& layer); + status_t invalidateLayerVisibility(const sp<LayerBase>& layer); private: friend class BClient; @@ -204,20 +184,26 @@ private: DisplayID display, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display, - int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + sp<LayerBaseClient> createNormalSurfaceLocked( + Client* client, DisplayID display, + int32_t id, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags); - LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createBlurSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createDimSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display, + sp<LayerBaseClient> createPushBuffersSurfaceLocked( + Client* client, DisplayID display, int32_t id, uint32_t w, uint32_t h, uint32_t flags); - status_t destroySurface(SurfaceID surface_id); - status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); + status_t removeSurface(SurfaceID surface_id); + status_t destroySurface(const sp<LayerBaseClient>& layer); + status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); class LayerVector { @@ -225,15 +211,15 @@ private: inline LayerVector() { } LayerVector(const LayerVector&); inline size_t size() const { return layers.size(); } - inline LayerBase*const* array() const { return layers.array(); } - ssize_t add(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t remove(LayerBase*); - ssize_t reorder(LayerBase*, Vector<LayerBase*>::compar_t); - ssize_t indexOf(LayerBase* key, size_t guess=0) const; - inline LayerBase* operator [] (size_t i) const { return layers[i]; } + inline sp<LayerBase> const* array() const { return layers.array(); } + ssize_t add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t remove(const sp<LayerBase>&); + ssize_t reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t); + ssize_t indexOf(const sp<LayerBase>& key, size_t guess=0) const; + inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; } private: - KeyedVector<LayerBase*, size_t> lookup; - Vector<LayerBase*> layers; + KeyedVector< sp<LayerBase> , size_t> lookup; + Vector< sp<LayerBase> > layers; }; struct State { @@ -247,25 +233,6 @@ private: uint8_t freezeDisplay; }; - class DelayedTransaction : public Thread - { - friend class SurfaceFlinger; - sp<SurfaceFlinger> mFlinger; - nsecs_t mDelay; - public: - DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay) - : Thread(false), mFlinger(flinger), mDelay(delay) { - } - virtual bool threadLoop() { - usleep(mDelay / 1000); - if (android_atomic_and(~1, - &mFlinger->mDeplayedTransactionPending) == 1) { - mFlinger->signalEvent(); - } - return false; - } - }; - virtual bool threadLoop(); virtual status_t readyToRun(); virtual void onFirstRef(); @@ -289,7 +256,6 @@ private: bool lockPageFlip(const LayerVector& currentLayers); void unlockPageFlip(const LayerVector& currentLayers); void handleRepaint(); - void handleDebugCpu(); void scheduleBroadcast(Client* client); void executeScheduledBroadcasts(); void postFramebuffer(); @@ -298,10 +264,10 @@ private: void destroyConnection(ClientID cid); - LayerBaseClient* getLayerUser_l(SurfaceID index) const; - status_t addLayer_l(LayerBase* layer); - status_t removeLayer_l(LayerBase* layer); - void destroy_all_removed_layers_l(); + sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const; + status_t addLayer_l(const sp<LayerBase>& layer); + status_t removeLayer_l(const sp<LayerBase>& layer); + status_t purgatorizeLayer_l(const sp<LayerBase>& layer); void free_resources_l(); uint32_t getTransactionFlags(uint32_t flags); @@ -323,6 +289,11 @@ private: void debugShowFPS() const; void drawWormhole() const; + + mutable MessageQueue mEventQueue; + + + // access must be protected by mStateLock mutable Mutex mStateLock; State mCurrentState; @@ -330,21 +301,21 @@ private: volatile int32_t mTransactionFlags; volatile int32_t mTransactionCount; Condition mTransactionCV; + SortedVector< sp<LayerBase> > mLayerPurgatory; + // protected by mStateLock (but we could use another lock) Tokenizer mTokens; DefaultKeyedVector<ClientID, Client*> mClientsMap; - DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap; + DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap; GraphicPlane mGraphicPlanes[1]; - SortedVector<LayerBase*> mRemovedLayers; + bool mLayersRemoved; Vector<Client*> mDisconnectedClients; // constant members (no synchronization needed for access) sp<MemoryDealer> mServerHeap; sp<IMemory> mServerCblkMemory; surface_flinger_cblk_t* mServerCblk; - sp<SurfaceHeapManager> mSurfaceHeapManager; - sp<GPUHardwareInterface> mGPU; GLuint mWormholeTexName; nsecs_t mBootTime; @@ -360,23 +331,13 @@ private: bool mFreezeDisplay; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; - friend class OrientationAnimation; - OrientationAnimation* mOrientationAnimation; - - // access protected by mDebugLock - mutable Mutex mDebugLock; - sp<CPUGauge> mCpuGauge; // don't use a lock for these, we don't care int mDebugRegion; - int mDebugCpu; - int mDebugFps; int mDebugBackground; // these are thread safe mutable Barrier mReadyToRunBarrier; - mutable SurfaceFlingerSynchro mSyncObject; - volatile int32_t mDeplayedTransactionPending; // atomic variables enum { diff --git a/libs/surfaceflinger/Tokenizer.cpp b/libs/surfaceflinger/Tokenizer.cpp index ef51d6a..be3a239 100644 --- a/libs/surfaceflinger/Tokenizer.cpp +++ b/libs/surfaceflinger/Tokenizer.cpp @@ -162,9 +162,10 @@ void Tokenizer::dump() const { const run_t* ranges = mRanges.array(); const size_t c = mRanges.size(); - printf("Tokenizer (%p, size = %lu)\n", this, c); + printf("Tokenizer (%p, size = %d)\n", this, int(c)); for (size_t i=0 ; i<c ; i++) { - printf("%lu: (%u, %u)\n", i, ranges[i].first, ranges[i].length); + printf("%u: (%u, %u)\n", i, + uint32_t(ranges[i].first), uint32_t(ranges[i].length)); } } diff --git a/libs/surfaceflinger/Transform.cpp b/libs/surfaceflinger/Transform.cpp index e8b0f45..1501536 100644 --- a/libs/surfaceflinger/Transform.cpp +++ b/libs/surfaceflinger/Transform.cpp @@ -177,10 +177,10 @@ Region Transform::transform(const Region& reg) const Region out; if (UNLIKELY(transformed())) { if (LIKELY(preserveRects())) { - Rect r; - Region::iterator iterator(reg); - while (iterator.iterate(&r)) { - out.orSelf(transform(r)); + Region::const_iterator it = reg.begin(); + Region::const_iterator const end = reg.end(); + while (it != end) { + out.orSelf(transform(*it++)); } } else { out.set(transform(reg.bounds())); diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp index 3e4035e..41c42d1 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp @@ -24,10 +24,6 @@ #include <utils/Log.h> #include <utils/StopWatch.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "BlurFilter.h" #include "LayerBase.h" #include "LayerOrientationAnim.h" @@ -57,8 +53,8 @@ const float DIM_TARGET = 0.40f; LayerOrientationAnim::LayerOrientationAnim( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) @@ -77,10 +73,10 @@ LayerOrientationAnim::LayerOrientationAnim( LayerOrientationAnim::~LayerOrientationAnim() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); + glDeleteTextures(1, &mTextureNameIn); } } @@ -108,11 +104,6 @@ void LayerOrientationAnim::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; - copybit_device_t* copybit = mFlinger->getBlitEngine(); - if (copybit) { - mCanUseCopyBit = true; - } } void LayerOrientationAnim::onOrientationCompleted() @@ -135,7 +126,7 @@ void LayerOrientationAnim::onDraw(const Region& clip) const // make a copy of what's on screen copybit_image_t image; - mBitmapOut.getBitmapSurface(&image); + mBitmapOut->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -194,7 +185,7 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -212,10 +203,10 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut } copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); copybit_image_t srcOut; - mBitmapOut.getBitmapSurface(&srcOut); + mBitmapOut->getBitmapSurface(&srcOut); const int w = dst.w*scale; const int h = dst.h*scale; @@ -225,78 +216,54 @@ void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut const copybit_rect_t srect = { 0, 0, src.w, src.h }; const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); - int err = NO_ERROR; - const int can_use_copybit = canUseCopybit(); - if (can_use_copybit) { - copybit_device_t* copybit = mFlinger->getBlitEngine(); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - - if (alphaIn > 0) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_ENABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaIn*255)); - err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - } + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (!err && alphaOut > 0.0f) { - region_iterator it(reg); - copybit->set_parameter(copybit, COPYBIT_BLUR, COPYBIT_DISABLE); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alphaOut*255)); - err = copybit->stretch(copybit, &dst, &srcOut, &drect, &srect, &it); - } - LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); + Transform tr; + tr.set(scale,0,0,scale); + tr.set(xc, yc); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; } - if (!can_use_copybit || err) { - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - Transform tr; - tr.set(scale,0,0,scale); - tr.set(xc, yc); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (alphaIn > 0.0f) { - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = int(alphaIn*255); - drawWithOpenGL(reg, mTextureNameIn, t); + if (alphaIn > 0.0f) { + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); } + self.mDrawingState.alpha = int(alphaIn*255); + drawWithOpenGL(reg, mTextureNameIn, t); + } - if (alphaOut > 0.0f) { - t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = int(alphaOut*255); - drawWithOpenGL(reg, mTextureName, t); + if (alphaOut > 0.0f) { + t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); } + self.mDrawingState.alpha = int(alphaOut*255); + drawWithOpenGL(reg, mTextureName, t); } } diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h index e86156d..a1a2654 100644 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h @@ -52,8 +52,8 @@ public: LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmapIn, - const LayerBitmap& bitmapOut); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnim(); void onOrientationCompleted(); @@ -90,8 +90,8 @@ private: }; OrientationAnimation* mAnim; - LayerBitmap mBitmapIn; - LayerBitmap mBitmapOut; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp index 89ffb19..dc6b632 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp @@ -23,10 +23,6 @@ #include <utils/Errors.h> #include <utils/Log.h> -#include <core/SkBitmap.h> - -#include <ui/EGLDisplaySurface.h> - #include "LayerBase.h" #include "LayerOrientationAnim.h" #include "LayerOrientationAnimRotate.h" @@ -51,10 +47,10 @@ const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; LayerOrientationAnimRotate::LayerOrientationAnimRotate( SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& bitmap, - const LayerBitmap& bitmapIn) + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut) : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmap(bitmap), mBitmapIn(bitmapIn), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), mTextureName(-1), mTextureNameIn(-1) { mStartTime = systemTime(); @@ -72,10 +68,10 @@ LayerOrientationAnimRotate::LayerOrientationAnimRotate( LayerOrientationAnimRotate::~LayerOrientationAnimRotate() { if (mTextureName != -1U) { - LayerBase::deletedTextures.add(mTextureName); + glDeleteTextures(1, &mTextureName); } if (mTextureNameIn != -1U) { - LayerBase::deletedTextures.add(mTextureNameIn); + glDeleteTextures(1, &mTextureNameIn); } } @@ -103,7 +99,6 @@ void LayerOrientationAnimRotate::validateVisibility(const Transform&) mTop = tr.ty(); transparentRegionScreen.clear(); mTransformed = true; - mCanUseCopyBit = false; } void LayerOrientationAnimRotate::onOrientationCompleted() @@ -126,7 +121,7 @@ void LayerOrientationAnimRotate::onDraw(const Region& clip) const if (mFirstRedraw) { // make a copy of what's on screen copybit_image_t image; - mBitmapIn.getBitmapSurface(&image); + mBitmapIn->getBitmapSurface(&image); const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.copyBackToImage(image); @@ -185,7 +180,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const copybit_image_t dst; const GraphicPlane& plane(graphicPlane(0)); const DisplayHardware& hw(plane.displayHardware()); - hw.getDisplaySurface(&dst); + //hw.getDisplaySurface(&dst); // clear screen // TODO: with update on demand, we may be able @@ -200,7 +195,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const const int h = dst.h; copybit_image_t src; - mBitmap.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); const copybit_rect_t srect = { 0, 0, src.w, src.h }; @@ -255,7 +250,7 @@ void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const tr.transform(self.mVertices[3], src.w, 0); copybit_image_t src; - mBitmapIn.getBitmapSurface(&src); + mBitmapIn->getBitmapSurface(&src); t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); if (UNLIKELY(mTextureNameIn == -1LU)) { mTextureNameIn = createTexture(); diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h index 3296f45..a88eec0 100644 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.h +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h @@ -40,8 +40,8 @@ public: LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, OrientationAnimation* anim, - const LayerBitmap& zoomOut, - const LayerBitmap& zoomIn); + const sp<Buffer>& bitmapIn, + const sp<Buffer>& bitmapOut); virtual ~LayerOrientationAnimRotate(); void onOrientationCompleted(); @@ -55,8 +55,8 @@ private: void drawScaled(float angle, float scale, float alpha) const; OrientationAnimation* mAnim; - LayerBitmap mBitmap; - LayerBitmap mBitmapIn; + sp<Buffer> mBitmapIn; + sp<Buffer> mBitmapOut; nsecs_t mStartTime; nsecs_t mFinishTime; bool mOrientationCompleted; diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp index 70eec8d..a6c9c28 100644 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlinger" - #include <stdint.h> #include <sys/types.h> #include <limits.h> @@ -24,7 +22,6 @@ #include "LayerOrientationAnimRotate.h" #include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" @@ -35,9 +32,6 @@ namespace android { OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) { - // allocate a memory-dealer for this the first time - mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( - ISurfaceComposer::eHardware); } OrientationAnimation::~OrientationAnimation() @@ -98,19 +92,14 @@ bool OrientationAnimation::prepare() const uint32_t w = hw.getWidth(); const uint32_t h = hw.getHeight(); - LayerBitmap bitmap; - bitmap.init(mTemporaryDealer); - bitmap.setBits(w, h, 1, hw.getFormat()); - - LayerBitmap bitmapIn; - bitmapIn.init(mTemporaryDealer); - bitmapIn.setBits(w, h, 1, hw.getFormat()); + sp<Buffer> bitmap = new Buffer(w, h, hw.getFormat()); + sp<Buffer> bitmapIn = new Buffer(w, h, hw.getFormat()); copybit_image_t front; - bitmap.getBitmapSurface(&front); - hw.copyFrontToImage(front); + bitmap->getBitmapSurface(&front); + hw.copyFrontToImage(front); // FIXME: we need an extension to do this - LayerOrientationAnimBase* l; + sp<LayerOrientationAnimBase> l; if (mType & 0x80) { l = new LayerOrientationAnimRotate( @@ -152,7 +141,7 @@ bool OrientationAnimation::finished() { mState = DONE; mFlinger->removeLayer(mLayerOrientationAnim); - mLayerOrientationAnim = NULL; + mLayerOrientationAnim.clear(); return true; } diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/purgatory/OrientationAnimation.h index cafa38d..8ba6621 100644 --- a/libs/surfaceflinger/OrientationAnimation.h +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.h @@ -72,8 +72,7 @@ private: bool finished(); sp<SurfaceFlinger> mFlinger; - sp<MemoryDealer> mTemporaryDealer; - LayerOrientationAnimBase* mLayerOrientationAnim; + sp< LayerOrientationAnimBase > mLayerOrientationAnim; int mState; uint32_t mType; }; diff --git a/libs/surfaceflinger/purgatory/VRamHeap.cpp b/libs/surfaceflinger/purgatory/VRamHeap.cpp new file mode 100644 index 0000000..f3ed790 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include <utils/MemoryDealer.h> +#include <utils/MemoryBase.h> +#include <utils/MemoryHeapPmem.h> +#include <utils/MemoryHeapBase.h> + +#include "GPUHardware/GPUHardware.h" +#include "SurfaceFlinger.h" +#include "VRamHeap.h" + +#if HAVE_ANDROID_OS +#include <linux/android_pmem.h> +#endif + + +namespace android { + +// --------------------------------------------------------------------------- + +/* + * Amount of memory we reserve for surface, per client in PMEM + * (PMEM is used for 2D acceleration) + * 8 MB of address space per client should be enough. + */ +static const int PMEM_SIZE = int(8 * 1024 * 1024); + +int SurfaceHeapManager::global_pmem_heap = 0; + +// --------------------------------------------------------------------------- + +SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, + size_t clientHeapSize) + : mFlinger(flinger), mClientHeapSize(clientHeapSize) +{ + SurfaceHeapManager::global_pmem_heap = 1; +} + +SurfaceHeapManager::~SurfaceHeapManager() +{ +} + +void SurfaceHeapManager::onFirstRef() +{ + if (global_pmem_heap) { + const char* device = "/dev/pmem"; + mPMemHeap = new PMemHeap(device, PMEM_SIZE); + if (mPMemHeap->base() == MAP_FAILED) { + mPMemHeap.clear(); + global_pmem_heap = 0; + } + } +} + +sp<MemoryDealer> SurfaceHeapManager::createHeap( + uint32_t flags, + pid_t client_pid, + const sp<MemoryDealer>& defaultAllocator) +{ + sp<MemoryDealer> dealer; + + if (flags & ISurfaceComposer::eGPU) { + // don't grant GPU memory if GPU is disabled + char value[PROPERTY_VALUE_MAX]; + property_get("debug.egl.hw", value, "1"); + if (atoi(value) == 0) { + flags &= ~ISurfaceComposer::eGPU; + } + } + + if (flags & ISurfaceComposer::eGPU) { + // FIXME: this is msm7201A specific, where gpu surfaces may not be secure + if (!(flags & ISurfaceComposer::eSecure)) { + // if GPU doesn't work, we try eHardware + flags |= ISurfaceComposer::eHardware; + // asked for GPU memory, try that first + dealer = mFlinger->getGPU()->request(client_pid); + } + } + + if (dealer == NULL) { + if (defaultAllocator != NULL) + // if a default allocator is given, use that + dealer = defaultAllocator; + } + + if (dealer == NULL) { + // always try h/w accelerated memory first + if (global_pmem_heap) { + const sp<PMemHeap>& heap(mPMemHeap); + if (dealer == NULL && heap != NULL) { + dealer = new MemoryDealer( + heap->createClientHeap(), + heap->getAllocator()); + } + } + } + + if (dealer == NULL) { + // return the ashmem allocator (software rendering) + dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap"); + } + return dealer; +} + +sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const +{ + Mutex::Autolock _l(mLock); + sp<SimpleBestFitAllocator> allocator; + + // this is only used for debugging + switch (type) { + case NATIVE_MEMORY_TYPE_PMEM: + if (mPMemHeap != 0) { + allocator = mPMemHeap->getAllocator(); + } + break; + } + return allocator; +} + +// --------------------------------------------------------------------------- + +PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved) + : MemoryHeapBase(device, size) +{ + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); + if (base() != MAP_FAILED) { + //LOGD("%s, %u bytes", device, virtualSize()); + if (reserved == 0) + reserved = virtualSize(); + mAllocator = new SimpleBestFitAllocator(reserved); + } +} + +PMemHeap::~PMemHeap() { + //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID()); +} + +sp<MemoryHeapPmem> PMemHeap::createClientHeap() { + sp<MemoryHeapBase> parentHeap(this); + return new MemoryHeapPmem(parentHeap); +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/VRamHeap.h b/libs/surfaceflinger/purgatory/VRamHeap.h new file mode 100644 index 0000000..9140167 --- /dev/null +++ b/libs/surfaceflinger/purgatory/VRamHeap.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_VRAM_HEAP_H +#define ANDROID_VRAM_HEAP_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/MemoryDealer.h> + +namespace android { + +// --------------------------------------------------------------------------- + +class PMemHeap; +class MemoryHeapPmem; +class SurfaceFlinger; + +// --------------------------------------------------------------------------- + +class SurfaceHeapManager : public RefBase +{ +public: + SurfaceHeapManager(const sp<SurfaceFlinger>& flinger, size_t clientHeapSize); + virtual ~SurfaceHeapManager(); + virtual void onFirstRef(); + /* use ISurfaceComposer flags eGPU|eHArdware|eSecure */ + sp<MemoryDealer> createHeap(uint32_t flags=0, pid_t client_pid = 0, + const sp<MemoryDealer>& defaultAllocator = 0); + + // used for debugging only... + sp<SimpleBestFitAllocator> getAllocator(int type) const; + +private: + sp<PMemHeap> getHeap(int type) const; + + sp<SurfaceFlinger> mFlinger; + mutable Mutex mLock; + size_t mClientHeapSize; + sp<PMemHeap> mPMemHeap; + static int global_pmem_heap; +}; + +// --------------------------------------------------------------------------- + +class PMemHeap : public MemoryHeapBase +{ +public: + PMemHeap(const char* const vram, + size_t size=0, size_t reserved=0); + virtual ~PMemHeap(); + + virtual const sp<SimpleBestFitAllocator>& getAllocator() const { + return mAllocator; + } + virtual sp<MemoryHeapPmem> createClientHeap(); + +private: + sp<SimpleBestFitAllocator> mAllocator; +}; + +// --------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_VRAM_HEAP_H diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk new file mode 100644 index 0000000..ef1532f --- /dev/null +++ b/libs/surfaceflinger/tests/resize/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + resize.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui + +LOCAL_MODULE:= test-resize + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp new file mode 100644 index 0000000..21c6ab6 --- /dev/null +++ b/libs/surfaceflinger/tests/resize/resize.cpp @@ -0,0 +1,60 @@ +#include <cutils/memory.h> + +#include <utils/IPCThreadState.h> +#include <utils/ProcessState.h> +#include <utils/IServiceManager.h> +#include <utils/Log.h> + +#include <ui/Surface.h> +#include <ui/ISurface.h> +#include <ui/Overlay.h> +#include <ui/SurfaceComposerClient.h> + +using namespace android; + +namespace android { +class Test { +public: + static const sp<ISurface>& getISurface(const sp<Surface>& s) { + return s->getISurface(); + } +}; +}; + +int main(int argc, char** argv) +{ + // set up the thread-pool + sp<ProcessState> proc(ProcessState::self()); + ProcessState::self()->startThreadPool(); + + // create a client to surfaceflinger + sp<SurfaceComposerClient> client = new SurfaceComposerClient(); + + // create pushbuffer surface + sp<Surface> surface = client->createSurface(getpid(), 0, 160, 240, + PIXEL_FORMAT_RGB_565); + + + client->openTransaction(); + surface->setLayer(100000); + client->closeTransaction(); + + Surface::SurfaceInfo info; + surface->lock(&info); + ssize_t bpr = info.s * bytesPerPixel(info.format); + android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h); + surface->unlockAndPost(); + + surface->lock(&info); + android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h); + surface->unlockAndPost(); + + client->openTransaction(); + surface->setSize(320, 240); + client->closeTransaction(); + + + IPCThreadState::self()->joinThreadPool(); + + return 0; +} diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index c6fd070..38ef8b9 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -2,12 +2,12 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ + BufferMapper.cpp \ Camera.cpp \ CameraParameters.cpp \ - EGLDisplaySurface.cpp \ - EGLNativeWindowSurface.cpp \ EventHub.cpp \ EventRecurrence.cpp \ + FramebufferNativeWindow.cpp \ KeyLayoutMap.cpp \ KeyCharacterMap.cpp \ ICamera.cpp \ @@ -28,7 +28,6 @@ LOCAL_SRC_FILES:= \ Time.cpp LOCAL_SHARED_LIBRARIES := \ - libcorecg \ libcutils \ libutils \ libbinder \ diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp new file mode 100644 index 0000000..92a9a86 --- /dev/null +++ b/libs/ui/BufferMapper.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "BufferMapper" + +#include <stdint.h> +#include <errno.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <ui/BufferMapper.h> +#include <ui/Rect.h> + +#include <hardware/gralloc.h> + + +namespace android { +// --------------------------------------------------------------------------- + +ANDROID_SINGLETON_STATIC_INSTANCE( BufferMapper ) + +BufferMapper::BufferMapper() + : mAllocMod(0) +{ + hw_module_t const* module; + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + if (err == 0) { + mAllocMod = (gralloc_module_t const *)module; + } +} + +status_t BufferMapper::registerBuffer(buffer_handle_t handle) +{ + status_t err = mAllocMod->registerBuffer(mAllocMod, handle); + LOGW_IF(err, "registerBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); + return err; +} + +status_t BufferMapper::unregisterBuffer(buffer_handle_t handle) +{ + status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle); + LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); + return err; +} + +status_t BufferMapper::lock(buffer_handle_t handle, + int usage, const Rect& bounds, void** vaddr) +{ + status_t err = mAllocMod->lock(mAllocMod, handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); + LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +status_t BufferMapper::unlock(buffer_handle_t handle) +{ + status_t err = mAllocMod->unlock(mAllocMod, handle); + LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); + return err; +} + +// --------------------------------------------------------------------------- +}; // namespace android diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp deleted file mode 100644 index d06c98b..0000000 --- a/libs/ui/EGLDisplaySurface.cpp +++ /dev/null @@ -1,519 +0,0 @@ -/* - ** - ** Copyright 2007 The Android Open Source Project - ** - ** Licensed under the Apache License Version 2.0(the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing software - ** distributed under the License is distributed on an "AS IS" BASIS - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#define LOG_TAG "EGLDisplaySurface" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> -#include <cutils/properties.h> - -#include <hardware/copybit.h> - -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> -#include <ui/Region.h> -#include <ui/EGLDisplaySurface.h> - -#if HAVE_ANDROID_OS -#include <linux/msm_mdp.h> -#endif - -#include <EGL/egl.h> - -#include <pixelflinger/format.h> - - -// ---------------------------------------------------------------------------- - -egl_native_window_t* android_createDisplaySurface() -{ - egl_native_window_t* s = new android::EGLDisplaySurface(); - s->memory_type = NATIVE_MEMORY_TYPE_GPU; - return s; -} - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLDisplaySurface::EGLDisplaySurface() - : EGLNativeSurface<EGLDisplaySurface>() -{ - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; - egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::connect = 0; - egl_native_window_t::disconnect = 0; - - mFb[0].data = 0; - mFb[1].data = 0; - mBlitEngine = 0; - egl_native_window_t::fd = mapFrameBuffer(); - if (egl_native_window_t::fd >= 0) { - - hw_module_t const* module; - if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { - copybit_open(module, &mBlitEngine); - } - - const float in2mm = 25.4f; - float refreshRate = 1000000000000000LLU / ( - float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres ) - * ( mInfo.left_margin + mInfo.right_margin + mInfo.xres ) - * mInfo.pixclock); - - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::width = buffer.width; - egl_native_window_t::height = buffer.height; - egl_native_window_t::stride = buffer.stride; - egl_native_window_t::format = buffer.format; - egl_native_window_t::base = intptr_t(mFb[0].data); - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - egl_native_window_t::flags = 0; - egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width; - egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height; - egl_native_window_t::fps = refreshRate; - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB; - // no error, set the magic word - egl_native_window_t::magic = 0x600913; - } - mSwapCount = -1; - mPageFlipCount = 0; -} - -EGLDisplaySurface::~EGLDisplaySurface() -{ - magic = 0; - copybit_close(mBlitEngine); - mBlitEngine = 0; - close(egl_native_window_t::fd); - munmap(mFb[0].data, mSize); - if (!(mFlags & PAGE_FLIP)) - free((void*)mFb[1].data); -} - -void EGLDisplaySurface::hook_incRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->incStrong(that); -} -void EGLDisplaySurface::hook_decRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->decStrong(that); -} -uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->swapBuffers(); -} - -void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) -{ - mInfo.reserved[0] = 0x54445055; // "UPDT"; - mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); - mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); -} - -uint32_t EGLDisplaySurface::swapBuffers() -{ -#define SHOW_FPS 0 -#if SHOW_FPS - nsecs_t now = systemTime(); - if (mSwapCount == -1) { - mTime = now; - mSwapCount = 0; - mSleep = 0; - } else { - nsecs_t d = now-mTime; - if (d >= seconds(1)) { - double fps = (mSwapCount * double(seconds(1))) / double(d); - LOGD("%f fps, sleep=%d / frame", - fps, (int)ns2us(mSleep / mSwapCount)); - mSwapCount = 0; - mTime = now; - mSleep = 0; - } else { - mSwapCount++; - } - } -#endif - /* If we can't do the page_flip, just copy the back buffer to the front */ - if (!(mFlags & PAGE_FLIP)) { - memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2); - return 0; - } - - // do the actual flip - mIndex = 1 - mIndex; - mInfo.activate = FB_ACTIVATE_VBL; - mInfo.yoffset = mIndex ? mInfo.yres : 0; - if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) { - LOGE("FBIOPUT_VSCREENINFO failed"); - return 0; - } - - /* - * this is a monstrous hack: Because the h/w accelerator is not able - * to render directly into the framebuffer, we need to copy its - * internal framebuffer out to the fb. - * oem[0] is used to access the fd of internal fb. - * All this is needed only in standalone mode, in SurfaceFlinger mode - * we control where the GPU renders. - * We do this only if we have copybit, since this hack is needed only - * with msm7k. - */ - if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) { - copybit_device_t *copybit = mBlitEngine; - copybit_rect_t sdrect = { 0, 0, - egl_native_window_t::width, egl_native_window_t::height }; - copybit_image_t dst = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, - egl_native_window_t::offset, - (void*)egl_native_window_t::base, - egl_native_window_t::fd - }; - copybit_image_t src = { - egl_native_window_t::width, - egl_native_window_t::height, - egl_native_window_t::format, // XXX: use proper format - egl_native_window_t::offset, - (void*)egl_native_window_t::base, // XXX: use proper base - egl_native_window_t::oem[0] - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); - copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it); - } - - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - -#if SHOW_FPS - mSleep += systemTime()-now; -#endif - - mPageFlipCount++; - - // We don't support screen-size changes for now - return 0; -} - -int32_t EGLDisplaySurface::getPageFlipCount() const -{ - return mPageFlipCount; -} - -void EGLDisplaySurface::copyFrontToBack(const Region& copyback) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t dst = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(copyback); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - /* no extra copy needed since we copied back to front instead of - * flipping */ - if (!(mFlags & PAGE_FLIP)) { - return; - } - - Region::iterator iterator(copyback); - if (iterator) { - Rect r; - uint8_t* const screen_src = mFb[ mIndex].data; - uint8_t* const screen_dst = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp; - uint8_t* s = screen_src + o; - uint8_t* d = screen_dst + o; - if (size == bpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += bpr; - s += bpr; - } while (--h > 0); - } - } - } - } -} - -void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[ mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - -void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst) -{ -#if HAVE_ANDROID_OS - if (mBlitEngine) { - copybit_image_t src = { - w: egl_native_window_t::stride, - h: egl_native_window_t::height, - format: egl_native_window_t::format, - offset: mFb[1-mIndex].data - mFb[0].data, - base: (void*)egl_native_window_t::base, - fd: egl_native_window_t::fd - }; - region_iterator it(Region(Rect( - egl_native_window_t::width, egl_native_window_t::height))); - mBlitEngine->blit(mBlitEngine, &dst, &src, &it); - } else -#endif - { - uint8_t* const screen_src = mFb[1-mIndex].data; - const size_t bpp = bytesPerPixel(egl_native_window_t::format); - const size_t bpr = egl_native_window_t::stride * bpp; - memcpy((char*)dst.base + dst.offset, screen_src, - bpr*egl_native_window_t::height); - } -} - - -status_t EGLDisplaySurface::mapFrameBuffer() -{ - char const * const device_template[] = { - "/dev/graphics/fb%u", - "/dev/fb%u", - 0 }; - int fd = -1; - int i=0; - char name[64]; - while ((fd==-1) && device_template[i]) { - snprintf(name, 64, device_template[i], 0); - fd = open(name, O_RDWR, 0); - i++; - } - if (fd < 0) - return -errno; - - struct fb_fix_screeninfo finfo; - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - struct fb_var_screeninfo info; - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - info.reserved[0] = 0; - info.reserved[1] = 0; - info.reserved[2] = 0; - info.xoffset = 0; - info.yoffset = 0; - info.yres_virtual = info.yres * 2; - info.bits_per_pixel = 16; - /* Explicitly request 5/6/5 */ - info.red.offset = 11; - info.red.length = 5; - info.green.offset = 5; - info.green.length = 6; - info.blue.offset = 0; - info.blue.length = 5; - info.transp.offset = 0; - info.transp.length = 0; - info.activate = FB_ACTIVATE_NOW; - - uint32_t flags = PAGE_FLIP; - if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); - } - - if (info.yres_virtual < info.yres * 2) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", - info.yres_virtual, info.yres*2); - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - int refreshRate = 1000000000000000LLU / - ( - uint64_t( info.upper_margin + info.lower_margin + info.yres ) - * ( info.left_margin + info.right_margin + info.xres ) - * info.pixclock - ); - - if (refreshRate == 0) { - // bleagh, bad info from the driver - refreshRate = 60*1000; // 60 Hz - } - if (int(info.width) <= 0 || int(info.height) <= 0) { - // the driver doesn't return that information - // default to 160 dpi - info.width = ((info.xres * 25.4f)/160.0f + 0.5f); - info.height = ((info.yres * 25.4f)/160.0f + 0.5f); - } - - float xdpi = (info.xres * 25.4f) / info.width; - float ydpi = (info.yres * 25.4f) / info.height; - float fps = refreshRate / 1000.0f; - - LOGI( "using (fd=%d)\n" - "id = %s\n" - "xres = %d px\n" - "yres = %d px\n" - "xres_virtual = %d px\n" - "yres_virtual = %d px\n" - "bpp = %d\n" - "r = %2u:%u\n" - "g = %2u:%u\n" - "b = %2u:%u\n", - fd, - finfo.id, - info.xres, - info.yres, - info.xres_virtual, - info.yres_virtual, - info.bits_per_pixel, - info.red.offset, info.red.length, - info.green.offset, info.green.length, - info.blue.offset, info.blue.length - ); - - LOGI( "width = %d mm (%f dpi)\n" - "height = %d mm (%f dpi)\n" - "refresh rate = %.2f Hz\n", - info.width, xdpi, - info.height, ydpi, - fps - ); - - - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - if (finfo.smem_len <= 0) - return -errno; - - /* - * Open and map the display. - */ - - void* buffer = (uint16_t*) mmap( - 0, finfo.smem_len, - PROT_READ | PROT_WRITE, - MAP_SHARED, - fd, 0); - - if (buffer == MAP_FAILED) - return -errno; - - // at least for now, always clear the fb - memset(buffer, 0, finfo.smem_len); - - uint8_t* offscreen[2]; - offscreen[0] = (uint8_t*)buffer; - if (flags & PAGE_FLIP) { - offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres; - } else { - offscreen[1] = (uint8_t*)malloc(finfo.smem_len); - if (offscreen[1] == 0) { - munmap(buffer, finfo.smem_len); - return NO_MEMORY; - } - } - - mFlags = flags; - mInfo = info; - mFinfo = finfo; - mSize = finfo.smem_len; - mIndex = 0; - for (int i=0 ; i<2 ; i++) { - mFb[i].version = sizeof(GGLSurface); - mFb[i].width = info.xres; - mFb[i].height = info.yres; - mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3); - mFb[i].data = (GGLubyte*)(offscreen[i]); - mFb[i].format = GGL_PIXEL_FORMAT_RGB_565; - } - return fd; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp deleted file mode 100644 index f1071cf..0000000 --- a/libs/ui/EGLNativeWindowSurface.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* -** -** Copyright 2007 The Android Open Source Project -** -** Licensed under the Apache License Version 2.0(the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing software -** distributed under the License is distributed on an "AS IS" BASIS -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "EGLNativeWindowSurface" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> - -#include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> -#include <ui/Rect.h> - -#include <EGL/egl.h> - -#include <pixelflinger/format.h> - -#include <ui/EGLNativeWindowSurface.h> - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface) - : EGLNativeSurface<EGLNativeWindowSurface>(), - mSurface(surface), mConnected(false) -{ - egl_native_window_t::magic = 0x600913; - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef; - egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers; - egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect; - egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect; - - DisplayInfo dinfo; - SurfaceComposerClient::getDisplayInfo(0, &dinfo); - egl_native_window_t::xdpi = dinfo.xdpi; - egl_native_window_t::ydpi = dinfo.ydpi; - egl_native_window_t::fps = dinfo.fps; - egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER; -} - -EGLNativeWindowSurface::~EGLNativeWindowSurface() -{ - disconnect(); - mSurface.clear(); - magic = 0; -} - -void EGLNativeWindowSurface::hook_incRef(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->incStrong(that); -} - -void EGLNativeWindowSurface::hook_decRef(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->decStrong(that); -} - -void EGLNativeWindowSurface::hook_connect(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->connect(); -} - -void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->disconnect(); -} - -uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - return that->swapBuffers(); -} - -void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h) -{ - mSurface->setSwapRectangle(Rect(l, t, l+w, t+h)); -} - -uint32_t EGLNativeWindowSurface::swapBuffers() -{ - const int w = egl_native_window_t::width; - const int h = egl_native_window_t::height; - const sp<Surface>& surface(mSurface); - Surface::SurfaceInfo info; - surface->unlockAndPost(); - surface->lock(&info); - // update the address of the buffer to draw to next - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - - // update size if it changed - if (w != int(info.w) || h != int(info.h)) { - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - return EGL_NATIVES_FLAG_SIZE_CHANGED; - } - return 0; -} - -void EGLNativeWindowSurface::connect() -{ - if (!mConnected) { - Surface::SurfaceInfo info; - mSurface->lock(&info); - mSurface->setSwapRectangle(Rect(info.w, info.h)); - mConnected = true; - - egl_native_window_t::width = info.w; - egl_native_window_t::height = info.h; - egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format); - egl_native_window_t::format = info.format; - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - // FIXME: egl_native_window_t::memory_type used to be set from - // mSurface, but we wanted to break this dependency. We set it to - // GPU because the software rendered doesn't care, but the h/w - // accelerator needs it. Eventually, this value should go away - // completely, since memory will be managed by OpenGL. - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU; - egl_native_window_t::fd = 0; - } -} - -void EGLNativeWindowSurface::disconnect() -{ - if (mConnected) { - mSurface->unlock(); - mConnected = false; - } -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp new file mode 100644 index 0000000..8c8fd6b --- /dev/null +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -0,0 +1,210 @@ +/* +** +** Copyright 2007 The Android Open Source Project +** +** Licensed under the Apache License Version 2.0(the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing software +** distributed under the License is distributed on an "AS IS" BASIS +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#define LOG_TAG "FramebufferNativeWindow" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <utils/threads.h> + +#include <ui/SurfaceComposerClient.h> +#include <ui/Rect.h> +#include <ui/FramebufferNativeWindow.h> + +#include <EGL/egl.h> + +#include <pixelflinger/format.h> +#include <pixelflinger/pixelflinger.h> + +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <private/ui/android_natives_priv.h> + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +class NativeBuffer + : public EGLNativeBase< + android_native_buffer_t, + NativeBuffer, + LightRefBase<NativeBuffer> > +{ +public: + NativeBuffer(int w, int h, int f, int u) : BASE() { + android_native_buffer_t::width = w; + android_native_buffer_t::height = h; + android_native_buffer_t::format = f; + android_native_buffer_t::usage = u; + } +private: + friend class LightRefBase<NativeBuffer>; + ~NativeBuffer() { }; // this class cannot be overloaded +}; + + +/* + * This implements the (main) framebuffer management. This class is used + * mostly by SurfaceFlinger, but also by command line GL application. + * + * In fact this is an implementation of android_native_window_t on top of + * the framebuffer. + * + * Currently it is pretty simple, it manages only two buffers (the front and + * back buffer). + * + */ + +FramebufferNativeWindow::FramebufferNativeWindow() + : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false) +{ + hw_module_t const* module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + int stride; + framebuffer_open(module, &fbDev); + gralloc_open(module, &grDev); + int err; + + + mUpdateOnDemand = (fbDev->setUpdateRect != 0); + + // initialize the buffer FIFO + mNumBuffers = 2; + mNumFreeBuffers = 2; + mBufferHead = mNumBuffers-1; + buffers[0] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + buffers[1] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); + + LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); + + LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + } + + const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; + const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi; + const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi; + const_cast<int&>(android_native_window_t::minSwapInterval) = + fbDev->minSwapInterval; + const_cast<int&>(android_native_window_t::maxSwapInterval) = + fbDev->maxSwapInterval; + + android_native_window_t::setSwapInterval = setSwapInterval; + android_native_window_t::dequeueBuffer = dequeueBuffer; + android_native_window_t::lockBuffer = lockBuffer; + android_native_window_t::queueBuffer = queueBuffer; +} + +FramebufferNativeWindow::~FramebufferNativeWindow() { + grDev->free(grDev, buffers[0]->handle); + grDev->free(grDev, buffers[1]->handle); + gralloc_close(grDev); + framebuffer_close(fbDev); +} + +status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r) +{ + if (!mUpdateOnDemand) { + return INVALID_OPERATION; + } + return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height()); +} + +int FramebufferNativeWindow::setSwapInterval( + android_native_window_t* window, int interval) +{ + framebuffer_device_t* fb = getSelf(window)->fbDev; + return fb->setSwapInterval(fb, interval); +} + +int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, + android_native_buffer_t** buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + + // wait for a free buffer + while (!self->mNumFreeBuffers) { + self->mCondition.wait(self->mutex); + } + // get this buffer + self->mNumFreeBuffers--; + int index = self->mBufferHead++; + if (self->mBufferHead >= self->mNumBuffers) + self->mBufferHead = 0; + + *buffer = self->buffers[index].get(); + + return 0; +} + +int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + + // wait that the buffer we're locking is not front anymore + while (self->front == buffer) { + self->mCondition.wait(self->mutex); + } + + return NO_ERROR; +} + +int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle; + int res = fb->post(fb, handle); + self->front = static_cast<NativeBuffer*>(buffer); + self->mNumFreeBuffers++; + self->mCondition.broadcast(); + return res; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + + +EGLNativeWindowType android_createDisplaySurface(void) +{ + return new android::FramebufferNativeWindow(); +} + diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index 1e60557..9fbae1e 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "ISurface" + #include <stdio.h> #include <stdint.h> #include <sys/types.h> @@ -23,10 +25,14 @@ #include <ui/ISurface.h> #include <ui/Overlay.h> +#include <ui/Surface.h> +#include <private/ui/SurfaceBuffer.h> namespace android { +// ---------------------------------------------------------------------- + ISurface::BufferHeap::BufferHeap() : w(0), h(0), hor_stride(0), ver_stride(0), format(0), transform(0), flags(0) @@ -55,6 +61,8 @@ ISurface::BufferHeap::~BufferHeap() { } +// ---------------------------------------------------------------------- + class BpSurface : public BpInterface<ISurface> { public: @@ -63,6 +71,15 @@ public: { } + virtual sp<SurfaceBuffer> getBuffer() + { + Parcel data, reply; + data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); + remote()->transact(GET_BUFFER, data, &reply); + sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply); + return buffer; + } + virtual status_t registerBuffers(const BufferHeap& buffers) { Parcel data, reply; @@ -116,6 +133,11 @@ status_t BnSurface::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { + case GET_BUFFER: { + CHECK_INTERFACE(ISurface, data, reply); + sp<SurfaceBuffer> buffer(getBuffer()); + return SurfaceBuffer::writeToParcel(reply, buffer.get()); + } case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); BufferHeap buffer; diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp index 5f558a1..2aa1405 100644 --- a/libs/ui/ISurfaceComposer.cpp +++ b/libs/ui/ISurfaceComposer.cpp @@ -114,36 +114,6 @@ public: remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t requestGPU( - const sp<IGPUCallback>& callback, gpu_info_t* gpu) - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(callback->asBinder()); - remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply); - gpu->regs = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->count = reply.readInt32(); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions); - if (gpu->count > maxCount) - return BAD_VALUE; - - for (size_t i=0 ; i<gpu->count ; i++) { - gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder()); - gpu->regions[i].reserved = reply.readInt32(); - } - return reply.readInt32(); - } - - virtual status_t revokeGPU() - { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply); - return reply.readInt32(); - } - virtual void signal() const { Parcel data, reply; @@ -196,10 +166,6 @@ status_t BnSurfaceComposer::onTransact( CHECK_INTERFACE(ISurfaceComposer, data, reply); bootFinished(); } break; - case REVOKE_GPU: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - reply->writeInt32( revokeGPU() ); - } break; case SIGNAL: { CHECK_INTERFACE(ISurfaceComposer, data, reply); signal(); @@ -209,27 +175,6 @@ status_t BnSurfaceComposer::onTransact( sp<IBinder> b = getCblk()->asBinder(); reply->writeStrongBinder(b); } break; - case REQUEST_GPU: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - // TODO: this should be protected by a permission - gpu_info_t info; - sp<IGPUCallback> callback - = interface_cast<IGPUCallback>(data.readStrongBinder()); - status_t res = requestGPU(callback, &info); - - // FIXME: for now, we don't dynamically allocate the regions array - size_t maxCount = sizeof(info.regions)/sizeof(*info.regions); - if (info.count > maxCount) - return BAD_VALUE; - - reply->writeStrongBinder(info.regs->asBinder()); - reply->writeInt32(info.count); - for (size_t i=0 ; i<info.count ; i++) { - reply->writeStrongBinder(info.regions[i].region->asBinder()); - reply->writeInt32(info.regions[i].reserved); - } - reply->writeInt32(res); - } break; default: return BBinder::onTransact(code, data, reply, flags); } @@ -238,41 +183,4 @@ status_t BnSurfaceComposer::onTransact( // ---------------------------------------------------------------------------- -enum { - // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService. - GPU_LOST = IBinder::FIRST_CALL_TRANSACTION -}; - -class BpGPUCallback : public BpInterface<IGPUCallback> -{ -public: - BpGPUCallback(const sp<IBinder>& impl) - : BpInterface<IGPUCallback>(impl) - { - } - - virtual void gpuLost() - { - Parcel data, reply; - data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor()); - remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback"); - -status_t BnGPUCallback::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ - switch(code) { - case GPU_LOST: { - CHECK_INTERFACE(IGPUCallback, data, reply); - gpuLost(); - return NO_ERROR; - } break; - default: - return BBinder::onTransact(code, data, reply, flags); - } -} - }; diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp index 329bd6e..46c12af 100644 --- a/libs/ui/ISurfaceFlingerClient.cpp +++ b/libs/ui/ISurfaceFlingerClient.cpp @@ -192,8 +192,6 @@ status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& par { token = parcel.readInt32(); identity = parcel.readInt32(); - heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); - heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder()); return NO_ERROR; } @@ -201,8 +199,6 @@ status_t ISurfaceFlingerClient::surface_data_t::writeToParcel(Parcel* parcel) co { parcel->writeInt32(token); parcel->writeInt32(identity); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); return NO_ERROR; } diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 26e694a..2e6b241 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -16,295 +16,653 @@ #define LOG_TAG "Region" -#include <stdio.h> -#include <utils/Atomic.h> -#include <utils/Debug.h> +#include <utils/Log.h> #include <utils/String8.h> + +#include <ui/Rect.h> #include <ui/Region.h> +#include <ui/Point.h> + +#include <private/ui/RegionHelper.h> + +// ---------------------------------------------------------------------------- +#define VALIDATE_REGIONS (false) +#define VALIDATE_WITH_CORECG (false) +// ---------------------------------------------------------------------------- + +#if VALIDATE_WITH_CORECG +#include <core/SkRegion.h> +#endif namespace android { +// ---------------------------------------------------------------------------- + +enum { + op_nand = region_operator<Rect>::op_nand, + op_and = region_operator<Rect>::op_and, + op_or = region_operator<Rect>::op_or, + op_xor = region_operator<Rect>::op_xor +}; // ---------------------------------------------------------------------------- Region::Region() + : mBounds(0,0) { } Region::Region(const Region& rhs) - : mRegion(rhs.mRegion) -{ -} - -Region::Region(const SkRegion& rhs) - : mRegion(rhs) -{ -} - -Region::~Region() + : mBounds(rhs.mBounds), mStorage(rhs.mStorage) { } Region::Region(const Rect& rhs) + : mBounds(rhs) { - set(rhs); } Region::Region(const Parcel& parcel) { - read(parcel); + status_t err = read(parcel); + LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err)); } Region::Region(const void* buffer) { - read(buffer); + status_t err = read(buffer); + LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err)); } -Region& Region::operator = (const Region& rhs) +Region::~Region() { - mRegion = rhs.mRegion; - return *this; } -const SkRegion& Region::toSkRegion() const +Region& Region::operator = (const Region& rhs) { - return mRegion; +#if VALIDATE_REGIONS + validate(rhs, "operator="); +#endif + mBounds = rhs.mBounds; + mStorage = rhs.mStorage; + return *this; } -Rect Region::bounds() const +void Region::clear() { - const SkIRect& b(mRegion.getBounds()); - return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom); + mBounds.clear(); + mStorage.clear(); } -void Region::clear() +void Region::set(const Rect& r) { - mRegion.setEmpty(); + mBounds = r; + mStorage.clear(); } -void Region::set(const Rect& r) +void Region::set(uint32_t w, uint32_t h) { - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.setRect(ir); + mBounds = Rect(int(w), int(h)); + mStorage.clear(); } // ---------------------------------------------------------------------------- -Region& Region::orSelf(const Rect& r) +void Region::addRectUnchecked(int l, int t, int r, int b) { - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.op(ir, SkRegion::kUnion_Op); - return *this; + mStorage.add(Rect(l,t,r,b)); +#if VALIDATE_REGIONS + validate(*this, "addRectUnchecked"); +#endif } -Region& Region::andSelf(const Rect& r) -{ - SkIRect ir; - ir.set(r.left, r.top, r.right, r.bottom); - mRegion.op(ir, SkRegion::kIntersect_Op); +// ---------------------------------------------------------------------------- + +Region& Region::orSelf(const Rect& r) { + return operationSelf(r, op_or); +} +Region& Region::andSelf(const Rect& r) { + return operationSelf(r, op_and); +} +Region& Region::subtractSelf(const Rect& r) { + return operationSelf(r, op_nand); +} +Region& Region::operationSelf(const Rect& r, int op) { + Region lhs(*this); + boolean_operation(op, *this, lhs, r); return *this; } // ---------------------------------------------------------------------------- Region& Region::orSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kUnion_Op); - return *this; + return operationSelf(rhs, op_or); } - Region& Region::andSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kIntersect_Op); - return *this; + return operationSelf(rhs, op_and); } - Region& Region::subtractSelf(const Region& rhs) { - mRegion.op(rhs.mRegion, SkRegion::kDifference_Op); + return operationSelf(rhs, op_nand); +} +Region& Region::operationSelf(const Region& rhs, int op) { + Region lhs(*this); + boolean_operation(op, *this, lhs, rhs); return *this; } Region& Region::translateSelf(int x, int y) { - if (x|y) mRegion.translate(x, y); + if (x|y) translate(*this, x, y); return *this; } -Region Region::merge(const Region& rhs) const { - Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kUnion_Op); - return result; -} +// ---------------------------------------------------------------------------- -Region Region::intersect(const Region& rhs) const { +const Region Region::merge(const Rect& rhs) const { + return operation(rhs, op_or); +} +const Region Region::intersect(const Rect& rhs) const { + return operation(rhs, op_and); +} +const Region Region::subtract(const Rect& rhs) const { + return operation(rhs, op_nand); +} +const Region Region::operation(const Rect& rhs, int op) const { Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kIntersect_Op); + boolean_operation(op, result, *this, rhs); return result; } -Region Region::subtract(const Region& rhs) const { +// ---------------------------------------------------------------------------- + +const Region Region::merge(const Region& rhs) const { + return operation(rhs, op_or); +} +const Region Region::intersect(const Region& rhs) const { + return operation(rhs, op_and); +} +const Region Region::subtract(const Region& rhs) const { + return operation(rhs, op_nand); +} +const Region Region::operation(const Region& rhs, int op) const { Region result; - result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op); + boolean_operation(op, result, *this, rhs); return result; } -Region Region::translate(int x, int y) const { +const Region Region::translate(int x, int y) const { Region result; - mRegion.translate(x, y, &result.mRegion); + translate(result, *this, x, y); return result; } // ---------------------------------------------------------------------------- Region& Region::orSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kUnion_Op); - return *this; + return operationSelf(rhs, dx, dy, op_or); } - Region& Region::andSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kIntersect_Op); - return *this; + return operationSelf(rhs, dx, dy, op_and); } - Region& Region::subtractSelf(const Region& rhs, int dx, int dy) { - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - mRegion.op(r, SkRegion::kDifference_Op); + return operationSelf(rhs, dx, dy, op_nand); +} +Region& Region::operationSelf(const Region& rhs, int dx, int dy, int op) { + Region lhs(*this); + boolean_operation(op, *this, lhs, rhs, dx, dy); return *this; } -Region Region::merge(const Region& rhs, int dx, int dy) const { +// ---------------------------------------------------------------------------- + +const Region Region::merge(const Region& rhs, int dx, int dy) const { + return operation(rhs, dx, dy, op_or); +} +const Region Region::intersect(const Region& rhs, int dx, int dy) const { + return operation(rhs, dx, dy, op_and); +} +const Region Region::subtract(const Region& rhs, int dx, int dy) const { + return operation(rhs, dx, dy, op_nand); +} +const Region Region::operation(const Region& rhs, int dx, int dy, int op) const { Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kUnion_Op); + boolean_operation(op, result, *this, rhs, dx, dy); return result; } -Region Region::intersect(const Region& rhs, int dx, int dy) const { - Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kIntersect_Op); +// ---------------------------------------------------------------------------- + +// This is our region rasterizer, which merges rects and spans together +// to obtain an optimal region. +class Region::rasterizer : public region_operator<Rect>::region_rasterizer +{ + Rect& bounds; + Vector<Rect>& storage; + Rect* head; + Rect* tail; + Vector<Rect> span; + Rect* cur; +public: + rasterizer(Region& reg) + : bounds(reg.mBounds), storage(reg.mStorage), head(), tail(), cur() { + bounds.top = bounds.bottom = 0; + bounds.left = INT_MAX; + bounds.right = INT_MIN; + storage.clear(); + } + + ~rasterizer() { + if (span.size()) { + flushSpan(); + } + if (storage.size()) { + bounds.top = storage.itemAt(0).top; + bounds.bottom = storage.top().bottom; + if (storage.size() == 1) { + storage.clear(); + } + } else { + bounds.left = 0; + bounds.right = 0; + } + } + + virtual void operator()(const Rect& rect) { + //LOGD(">>> %3d, %3d, %3d, %3d", + // rect.left, rect.top, rect.right, rect.bottom); + if (span.size()) { + if (cur->top != rect.top) { + flushSpan(); + } else if (cur->right == rect.left) { + cur->right = rect.right; + return; + } + } + span.add(rect); + cur = span.editArray() + (span.size() - 1); + } +private: + template<typename T> + static inline T min(T rhs, T lhs) { return rhs < lhs ? rhs : lhs; } + template<typename T> + static inline T max(T rhs, T lhs) { return rhs > lhs ? rhs : lhs; } + void flushSpan() { + bool merge = false; + if (tail-head == ssize_t(span.size())) { + Rect const* p = cur; + Rect const* q = head; + if (p->top == q->bottom) { + merge = true; + while (q != tail) { + if ((p->left != q->left) || (p->right != q->right)) { + merge = false; + break; + } + p++, q++; + } + } + } + if (merge) { + const int bottom = span[0].bottom; + Rect* r = head; + while (r != tail) { + r->bottom = bottom; + r++; + } + } else { + bounds.left = min(span.itemAt(0).left, bounds.left); + bounds.right = max(span.top().right, bounds.right); + storage.appendVector(span); + tail = storage.editArray() + storage.size(); + head = tail - span.size(); + } + span.clear(); + } +}; + +bool Region::validate(const Region& reg, const char* name) +{ + bool result = true; + const_iterator cur = reg.begin(); + const_iterator const tail = reg.end(); + const_iterator prev = cur++; + Rect b(*prev); + while (cur != tail) { + b.left = b.left < cur->left ? b.left : cur->left; + b.top = b.top < cur->top ? b.top : cur->top; + b.right = b.right > cur->right ? b.right : cur->right; + b.bottom = b.bottom > cur->bottom ? b.bottom : cur->bottom; + if (cur->top == prev->top) { + if (cur->bottom != prev->bottom) { + LOGE("%s: invalid span %p", name, cur); + result = false; + } else if (cur->left < prev->right) { + LOGE("%s: spans overlap horizontally prev=%p, cur=%p", + name, prev, cur); + result = false; + } + } else if (cur->top < prev->bottom) { + LOGE("%s: spans overlap vertically prev=%p, cur=%p", + name, prev, cur); + result = false; + } + prev = cur; + cur++; + } + if (b != reg.getBounds()) { + result = false; + LOGE("%s: invalid bounds [%d,%d,%d,%d] vs. [%d,%d,%d,%d]", name, + b.left, b.top, b.right, b.bottom, + reg.getBounds().left, reg.getBounds().top, + reg.getBounds().right, reg.getBounds().bottom); + } + if (result == false) { + reg.dump(name); + } return result; } -Region Region::subtract(const Region& rhs, int dx, int dy) const { - Region result; - SkRegion r(rhs.mRegion); - r.translate(dx, dy); - result.mRegion.op(mRegion, r, SkRegion::kDifference_Op); - return result; +void Region::boolean_operation(int op, Region& dst, + const Region& lhs, + const Region& rhs, int dx, int dy) +{ + size_t lhs_count; + Rect const * const lhs_rects = lhs.getArray(&lhs_count); + + size_t rhs_count; + Rect const * const rhs_rects = rhs.getArray(&rhs_count); + + region_operator<Rect>::region lhs_region(lhs_rects, lhs_count); + region_operator<Rect>::region rhs_region(rhs_rects, rhs_count, dx, dy); + region_operator<Rect> operation(op, lhs_region, rhs_region); + { // scope for rasterizer (dtor has side effects) + rasterizer r(dst); + operation(r); + } + +#if VALIDATE_REGIONS + validate(lhs, "boolean_operation: lhs"); + validate(rhs, "boolean_operation: rhs"); + validate(dst, "boolean_operation: dst"); +#endif + +#if VALIDATE_WITH_CORECG + SkRegion sk_lhs; + SkRegion sk_rhs; + SkRegion sk_dst; + + for (size_t i=0 ; i<lhs_count ; i++) + sk_lhs.op( + lhs_rects[i].left + dx, + lhs_rects[i].top + dy, + lhs_rects[i].right + dx, + lhs_rects[i].bottom + dy, + SkRegion::kUnion_Op); + + for (size_t i=0 ; i<rhs_count ; i++) + sk_rhs.op( + rhs_rects[i].left + dx, + rhs_rects[i].top + dy, + rhs_rects[i].right + dx, + rhs_rects[i].bottom + dy, + SkRegion::kUnion_Op); + + const char* name = "---"; + SkRegion::Op sk_op; + switch (op) { + case op_or: sk_op = SkRegion::kUnion_Op; name="OR"; break; + case op_and: sk_op = SkRegion::kIntersect_Op; name="AND"; break; + case op_nand: sk_op = SkRegion::kDifference_Op; name="NAND"; break; + } + sk_dst.op(sk_lhs, sk_rhs, sk_op); + + if (sk_dst.isEmpty() && dst.isEmpty()) + return; + + bool same = true; + Region::const_iterator head = dst.begin(); + Region::const_iterator const tail = dst.end(); + SkRegion::Iterator it(sk_dst); + while (!it.done()) { + if (head != tail) { + if ( + head->left != it.rect().fLeft || + head->top != it.rect().fTop || + head->right != it.rect().fRight || + head->bottom != it.rect().fBottom + ) { + same = false; + break; + } + } else { + same = false; + break; + } + head++; + it.next(); + } + + if (head != tail) { + same = false; + } + + if(!same) { + LOGD("---\nregion boolean %s failed", name); + lhs.dump("lhs"); + rhs.dump("rhs"); + dst.dump("dst"); + LOGD("should be"); + SkRegion::Iterator it(sk_dst); + while (!it.done()) { + LOGD(" [%3d, %3d, %3d, %3d]", + it.rect().fLeft, + it.rect().fTop, + it.rect().fRight, + it.rect().fBottom); + it.next(); + } + } +#endif } -// ---------------------------------------------------------------------------- +void Region::boolean_operation(int op, Region& dst, + const Region& lhs, + const Rect& rhs, int dx, int dy) +{ +#if VALIDATE_WITH_CORECG || VALIDATE_REGIONS + boolean_operation(op, dst, lhs, Region(rhs), dx, dy); +#else + size_t lhs_count; + Rect const * const lhs_rects = lhs.getArray(&lhs_count); + + region_operator<Rect>::region lhs_region(lhs_rects, lhs_count); + region_operator<Rect>::region rhs_region(&rhs, 1, dx, dy); + region_operator<Rect> operation(op, lhs_region, rhs_region); + { // scope for rasterizer (dtor has side effects) + rasterizer r(dst); + operation(r); + } + +#endif +} -Region::iterator::iterator(const Region& r) - : mIt(r.mRegion) +void Region::boolean_operation(int op, Region& dst, + const Region& lhs, const Region& rhs) { + boolean_operation(op, dst, lhs, rhs, 0, 0); } -int Region::iterator::iterate(Rect* rect) +void Region::boolean_operation(int op, Region& dst, + const Region& lhs, const Rect& rhs) { - if (mIt.done()) - return 0; - const SkIRect& r(mIt.rect()); - rect->left = r.fLeft; - rect->top = r.fTop; - rect->right = r.fRight; - rect->bottom= r.fBottom; - mIt.next(); - return 1; + boolean_operation(op, dst, lhs, rhs, 0, 0); } -// ---------------------------------------------------------------------------- +void Region::translate(Region& reg, int dx, int dy) +{ + if (!reg.isEmpty()) { +#if VALIDATE_REGIONS + validate(reg, "translate (before)"); +#endif + reg.mBounds.translate(dx, dy); + size_t count = reg.mStorage.size(); + Rect* rects = reg.mStorage.editArray(); + while (count) { + rects->translate(dx, dy); + rects++; + count--; + } +#if VALIDATE_REGIONS + validate(reg, "translate (after)"); +#endif + } +} + +void Region::translate(Region& dst, const Region& reg, int dx, int dy) +{ + dst = reg; + translate(dst, dx, dy); +} -// we write a 4byte size ahead of the actual region, so we know how much we'll need for reading +// ---------------------------------------------------------------------------- status_t Region::write(Parcel& parcel) const { - int32_t size = mRegion.flatten(NULL); - parcel.writeInt32(size); - mRegion.flatten(parcel.writeInplace(size)); +#if VALIDATE_REGIONS + validate(*this, "write(Parcel)"); +#endif + status_t err; + const size_t count = mStorage.size(); + const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect); + void* buffer = parcel.writeInplace(sizeNeeded); + if (!buffer) return NO_MEMORY; + ssize_t written = Region::write(buffer, sizeNeeded); + if (written < 0) return status_t(written); return NO_ERROR; } status_t Region::read(const Parcel& parcel) { - size_t size = parcel.readInt32(); - mRegion.unflatten(parcel.readInplace(size)); + void const* buffer = parcel.readInplace(sizeof(int32_t)); + if (!buffer) return NO_MEMORY; + const size_t count = *static_cast<int32_t const *>(buffer); + void const* dummy = parcel.readInplace((1+count)*sizeof(Rect)); + if (!dummy) return NO_MEMORY; + const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect); + const ssize_t read = Region::read(buffer); + if (read < 0) return status_t(read); +#if VALIDATE_REGIONS + validate(*this, "read(Parcel)"); +#endif return NO_ERROR; } ssize_t Region::write(void* buffer, size_t size) const { - size_t sizeNeeded = mRegion.flatten(NULL); +#if VALIDATE_REGIONS + validate(*this, "write(buffer)"); +#endif + const size_t count = mStorage.size(); + const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect); if (sizeNeeded > size) return NO_MEMORY; - return mRegion.flatten(buffer); + int32_t* const p = static_cast<int32_t*>(buffer); + *p = count; + memcpy(p+1, &mBounds, sizeof(Rect)); + if (count) { + memcpy(p+5, mStorage.array(), count*sizeof(Rect)); + } + return ssize_t(sizeNeeded); } ssize_t Region::read(const void* buffer) { - return mRegion.unflatten(buffer); + int32_t const* const p = static_cast<int32_t const*>(buffer); + const size_t count = *p; + memcpy(&mBounds, p+1, sizeof(Rect)); + mStorage.clear(); + if (count) { + mStorage.insertAt(0, count); + memcpy(mStorage.editArray(), p+5, count*sizeof(Rect)); + } +#if VALIDATE_REGIONS + validate(*this, "read(buffer)"); +#endif + return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect)); } ssize_t Region::writeEmpty(void* buffer, size_t size) { - if (size < 4) return NO_MEMORY; - // this needs to stay in sync with SkRegion - *static_cast<int32_t*>(buffer) = -1; - return 4; + const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect); + if (sizeNeeded > size) return NO_MEMORY; + int32_t* const p = static_cast<int32_t*>(buffer); + memset(p, 0, sizeNeeded); + return ssize_t(sizeNeeded); } bool Region::isEmpty(void* buffer) { - // this needs to stay in sync with SkRegion - return *static_cast<int32_t*>(buffer) == -1; + int32_t const* const p = static_cast<int32_t const*>(buffer); + Rect const* const b = reinterpret_cast<Rect const *>(p+1); + return b->isEmpty(); +} + +// ---------------------------------------------------------------------------- + +Region::const_iterator Region::begin() const { + return isRect() ? &mBounds : mStorage.array(); +} + +Region::const_iterator Region::end() const { + return isRect() ? ((&mBounds) + 1) : (mStorage.array() + mStorage.size()); +} + +Rect const* Region::getArray(size_t* count) const { + const_iterator const b(begin()); + const_iterator const e(end()); + if (count) *count = e-b; + return b; } -size_t Region::rects(Vector<Rect>& rectList) const +size_t Region::getRects(Vector<Rect>& rectList) const { - rectList.clear(); - if (!isEmpty()) { - SkRegion::Iterator iterator(mRegion); - while( !iterator.done() ) { - const SkIRect& ir(iterator.rect()); - rectList.push(Rect(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom)); - iterator.next(); - } + rectList = mStorage; + if (rectList.isEmpty()) { + rectList.clear(); + rectList.add(mBounds); } return rectList.size(); } +// ---------------------------------------------------------------------------- + void Region::dump(String8& out, const char* what, uint32_t flags) const { (void)flags; - Vector<Rect> r; - rects(r); - + const_iterator head = begin(); + const_iterator const tail = end(); + size_t SIZE = 256; char buffer[SIZE]; - - snprintf(buffer, SIZE, " Region %s (this=%p, count=%d)\n", what, this, r.size()); + + snprintf(buffer, SIZE, " Region %s (this=%p, count=%d)\n", + what, this, tail-head); out.append(buffer); - for (size_t i=0 ; i<r.size() ; i++) { + while (head != tail) { snprintf(buffer, SIZE, " [%3d, %3d, %3d, %3d]\n", - r[i].left, r[i].top,r[i].right,r[i].bottom); + head->left, head->top, head->right, head->bottom); out.append(buffer); + head++; } } void Region::dump(const char* what, uint32_t flags) const { (void)flags; - Vector<Rect> r; - rects(r); - LOGD(" Region %s (this=%p, count=%d)\n", what, this, r.size()); - for (size_t i=0 ; i<r.size() ; i++) { + const_iterator head = begin(); + const_iterator const tail = end(); + LOGD(" Region %s (this=%p, count=%d)\n", what, this, tail-head); + while (head != tail) { LOGD(" [%3d, %3d, %3d, %3d]\n", - r[i].left, r[i].top,r[i].right,r[i].bottom); + head->left, head->top, head->right, head->bottom); + head++; } } diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 05cc529..b8b428f 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -23,202 +23,319 @@ #include <sys/types.h> #include <sys/stat.h> -#include <utils/Atomic.h> #include <utils/Errors.h> #include <utils/threads.h> #include <binder/IPCThreadState.h> #include <binder/IMemory.h> #include <utils/Log.h> +#include <ui/DisplayInfo.h> +#include <ui/BufferMapper.h> #include <ui/ISurface.h> #include <ui/Surface.h> #include <ui/SurfaceComposerClient.h> #include <ui/Rect.h> +#include <pixelflinger/pixelflinger.h> + #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> +#include <private/ui/SurfaceBuffer.h> namespace android { -// --------------------------------------------------------------------------- +// ============================================================================ +// SurfaceBuffer +// ============================================================================ -Surface::Surface(const sp<SurfaceComposerClient>& client, - const sp<ISurface>& surface, - const ISurfaceFlingerClient::surface_data_t& data, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - bool owner) - : mClient(client), mSurface(surface), - mToken(data.token), mIdentity(data.identity), - mFormat(format), mFlags(flags), mOwner(owner) +SurfaceBuffer::SurfaceBuffer() + : BASE(), mOwner(false), mBufferMapper(BufferMapper::get()) { - mSwapRectangle.makeInvalid(); - mSurfaceHeapBase[0] = 0; - mSurfaceHeapBase[1] = 0; - mHeap[0] = data.heap[0]; - mHeap[1] = data.heap[1]; -} - -Surface::Surface(Surface const* rhs) - : mOwner(false) -{ - mToken = rhs->mToken; - mIdentity= rhs->mIdentity; - mClient = rhs->mClient; - mSurface = rhs->mSurface; - mHeap[0] = rhs->mHeap[0]; - mHeap[1] = rhs->mHeap[1]; - mFormat = rhs->mFormat; - mFlags = rhs->mFlags; - mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0]; - mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1]; - mSwapRectangle.makeInvalid(); + width = + height = + stride = + format = + usage = 0; + handle = NULL; } -Surface::~Surface() +SurfaceBuffer::SurfaceBuffer(const Parcel& data) + : BASE(), mOwner(true), mBufferMapper(BufferMapper::get()) { - if (mOwner && mToken>=0 && mClient!=0) { - mClient->destroySurface(mToken); - } - mClient.clear(); - mSurface.clear(); - mHeap[0].clear(); - mHeap[1].clear(); - IPCThreadState::self()->flushCommands(); + // we own the handle in this case + width = data.readInt32(); + height = data.readInt32(); + stride = data.readInt32(); + format = data.readInt32(); + usage = data.readInt32(); + handle = data.readNativeHandle(); } -sp<Surface> Surface::dup() const +SurfaceBuffer::~SurfaceBuffer() { - Surface const * r = this; - if (this && mOwner) { - // the only reason we need to do this is because of Java's garbage - // collector: because we're creating a copy of the Surface - // instead of a reference, we can garantee that when our last - // reference goes away, the real surface will be deleted. - // Without this hack (the code is correct too), we'd have to - // wait for a GC for the surface to go away. - r = new Surface(this); + if (handle && mOwner) { + native_handle_close(handle); + native_handle_delete(const_cast<native_handle*>(handle)); } - return const_cast<Surface*>(r); } -status_t Surface::nextBuffer(SurfaceInfo* info) { - return mClient->nextBuffer(this, info); +status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr) +{ + const Rect lockBounds(width, height); + status_t res = lock(usage, lockBounds, vaddr); + return res; } -status_t Surface::lock(SurfaceInfo* info, bool blocking) { - return Surface::lock(info, NULL, blocking); +status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) +{ + status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); + return res; } -status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->lockSurface(this, info, dirty, blocking); +status_t SurfaceBuffer::unlock() +{ + status_t res = getBufferMapper().unlock(handle); + return res; } -status_t Surface::unlockAndPost() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockAndPostSurface(this); +status_t SurfaceBuffer::writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer) +{ + reply->writeInt32(buffer->width); + reply->writeInt32(buffer->height); + reply->writeInt32(buffer->stride); + reply->writeInt32(buffer->format); + reply->writeInt32(buffer->usage); + reply->writeNativeHandle(buffer->handle); + return NO_ERROR; } -status_t Surface::unlock() { - if (heapBase(0) == 0) return INVALID_OPERATION; - if (heapBase(1) == 0) return INVALID_OPERATION; - return mClient->unlockSurface(this); +// ---------------------------------------------------------------------- + +static void copyBlt( + const sp<SurfaceBuffer>& dst, + const sp<SurfaceBuffer>& src, + const Region& reg) +{ + uint8_t const * src_bits; + src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); + + uint8_t* dst_bits; + dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); + + size_t c; + Rect const* const rects = reg.getArray(&c); + + if (c) { + // NOTE: dst and src must be the same format + const size_t bpp = bytesPerPixel(src->format); + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + for (size_t i=0 ; i<c ; i++) { + const Rect& r = rects[i]; + ssize_t h = r.height(); + if (h <= 0) continue; + size_t size = r.width() * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); + } + } + + src->unlock(); + dst->unlock(); } -status_t Surface::setLayer(int32_t layer) { - return mClient->setLayer(this, layer); +// ============================================================================ +// SurfaceControl +// ============================================================================ + +SurfaceControl::SurfaceControl( + const sp<SurfaceComposerClient>& client, + const sp<ISurface>& surface, + const ISurfaceFlingerClient::surface_data_t& data, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) + : mClient(client), mSurface(surface), + mToken(data.token), mIdentity(data.identity), + mFormat(format), mFlags(flags) +{ } -status_t Surface::setPosition(int32_t x, int32_t y) { - return mClient->setPosition(this, x, y); + +SurfaceControl::~SurfaceControl() +{ + destroy(); } -status_t Surface::setSize(uint32_t w, uint32_t h) { - return mClient->setSize(this, w, h); + +void SurfaceControl::destroy() +{ + if (isValid()) { + mClient->destroySurface(mToken); + } + + // clear all references and trigger an IPC now, to make sure things + // happen without delay, since these resources are quite heavy. + mClient.clear(); + mSurface.clear(); + IPCThreadState::self()->flushCommands(); +} + +void SurfaceControl::clear() +{ + // here, the window manager tells us explicitly that we should destroy + // the surface's resource. Soon after this call, it will also release + // its last reference (which will call the dtor); however, it is possible + // that a client living in the same process still holds references which + // would delay the call to the dtor -- that is why we need this explicit + // "clear()" call. + destroy(); } -status_t Surface::hide() { - return mClient->hide(this); + +bool SurfaceControl::isSameSurface( + const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) +{ + if (lhs == 0 || rhs == 0) + return false; + return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); } -status_t Surface::show(int32_t layer) { - return mClient->show(this, layer); + +status_t SurfaceControl::setLayer(int32_t layer) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setLayer(mToken, layer); } -status_t Surface::freeze() { - return mClient->freeze(this); +status_t SurfaceControl::setPosition(int32_t x, int32_t y) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setPosition(mToken, x, y); } -status_t Surface::unfreeze() { - return mClient->unfreeze(this); +status_t SurfaceControl::setSize(uint32_t w, uint32_t h) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setSize(mToken, w, h); } -status_t Surface::setFlags(uint32_t flags, uint32_t mask) { - return mClient->setFlags(this, flags, mask); +status_t SurfaceControl::hide() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->hide(mToken); } -status_t Surface::setTransparentRegionHint(const Region& transparent) { - return mClient->setTransparentRegionHint(this, transparent); +status_t SurfaceControl::show(int32_t layer) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->show(mToken, layer); } -status_t Surface::setAlpha(float alpha) { - return mClient->setAlpha(this, alpha); +status_t SurfaceControl::freeze() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->freeze(mToken); } -status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { - return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy); +status_t SurfaceControl::unfreeze() { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->unfreeze(mToken); } -status_t Surface::setFreezeTint(uint32_t tint) { - return mClient->setFreezeTint(this, tint); +status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setFlags(mToken, flags, mask); } - -Region Surface::dirtyRegion() const { - return mDirtyRegion; +status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setTransparentRegionHint(mToken, transparent); } -void Surface::setDirtyRegion(const Region& region) const { - mDirtyRegion = region; +status_t SurfaceControl::setAlpha(float alpha) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setAlpha(mToken, alpha); } -const Rect& Surface::swapRectangle() const { - return mSwapRectangle; +status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setMatrix(mToken, dsdx, dtdx, dsdy, dtdy); } -void Surface::setSwapRectangle(const Rect& r) { - mSwapRectangle = r; +status_t SurfaceControl::setFreezeTint(uint32_t tint) { + const sp<SurfaceComposerClient>& client(mClient); + if (client == 0) return NO_INIT; + status_t err = validate(client->mControl); + if (err < 0) return err; + return client->setFreezeTint(mToken, tint); } -sp<Surface> Surface::readFromParcel(Parcel* parcel) +status_t SurfaceControl::validate(per_client_cblk_t const* cblk) const { - sp<SurfaceComposerClient> client; - ISurfaceFlingerClient::surface_data_t data; - sp<IBinder> clientBinder= parcel->readStrongBinder(); - sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder()); - data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); - data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder()); - data.token = parcel->readInt32(); - data.identity = parcel->readInt32(); - PixelFormat format = parcel->readInt32(); - uint32_t flags = parcel->readInt32(); - - if (clientBinder != NULL) - client = SurfaceComposerClient::clientForConnection(clientBinder); - - return new Surface(client, surface, data, 0, 0, format, flags, false); + if (mToken<0 || mClient==0) { + LOGE("invalid token (%d, identity=%u) or client (%p)", + mToken, mIdentity, mClient.get()); + return NO_INIT; + } + if (cblk == 0) { + LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + return NO_INIT; + } + status_t err = cblk->validate(mToken); + if (err != NO_ERROR) { + LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", + mToken, mIdentity, err, strerror(-err)); + return err; + } + if (mIdentity != uint32_t(cblk->layers[mToken].identity)) { + LOGE("using an invalid surface id=%d, identity=%u should be %d", + mToken, mIdentity, cblk->layers[mToken].identity); + return NO_INIT; + } + return NO_ERROR; } -status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) +status_t SurfaceControl::writeSurfaceToParcel( + const sp<SurfaceControl>& control, Parcel* parcel) { - uint32_t flags=0; - uint32_t format=0; + uint32_t flags = 0; + uint32_t format = 0; SurfaceID token = -1; uint32_t identity = 0; sp<SurfaceComposerClient> client; sp<ISurface> sur; - sp<IMemoryHeap> heap[2]; - if (surface->isValid()) { - token = surface->mToken; - identity = surface->mIdentity; - client = surface->mClient; - sur = surface->mSurface; - heap[0] = surface->mHeap[0]; - heap[1] = surface->mHeap[1]; - format = surface->mFormat; - flags = surface->mFlags; + if (SurfaceControl::isValid(control)) { + token = control->mToken; + identity = control->mIdentity; + client = control->mClient; + sur = control->mSurface; + format = control->mFormat; + flags = control->mFlags; } parcel->writeStrongBinder(client!=0 ? client->connection() : NULL); parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); - parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL); - parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL); parcel->writeInt32(token); parcel->writeInt32(identity); parcel->writeInt32(format); @@ -226,30 +343,348 @@ status_t Surface::writeToParcel(const sp<Surface>& surface, Parcel* parcel) return NO_ERROR; } -bool Surface::isSameSurface(const sp<Surface>& lhs, const sp<Surface>& rhs) +sp<Surface> SurfaceControl::getSurface() const +{ + Mutex::Autolock _l(mLock); + if (mSurfaceData == 0) { + mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); + } + return mSurfaceData; +} + +// ============================================================================ +// Surface +// ============================================================================ + +Surface::Surface(const sp<SurfaceControl>& surface) + : mClient(surface->mClient), mSurface(surface->mSurface), + mToken(surface->mToken), mIdentity(surface->mIdentity), + mFormat(surface->mFormat), mFlags(surface->mFlags), + mBufferMapper(BufferMapper::get()) +{ + init(); +} + +Surface::Surface(const Parcel& parcel) + : mBufferMapper(BufferMapper::get()) +{ + sp<IBinder> clientBinder = parcel.readStrongBinder(); + mSurface = interface_cast<ISurface>(parcel.readStrongBinder()); + mToken = parcel.readInt32(); + mIdentity = parcel.readInt32(); + mFormat = parcel.readInt32(); + mFlags = parcel.readInt32(); + + if (clientBinder != NULL) + mClient = SurfaceComposerClient::clientForConnection(clientBinder); + + init(); +} + +void Surface::init() +{ + android_native_window_t::setSwapInterval = setSwapInterval; + android_native_window_t::dequeueBuffer = dequeueBuffer; + android_native_window_t::lockBuffer = lockBuffer; + android_native_window_t::queueBuffer = queueBuffer; + mSwapRectangle.makeInvalid(); + DisplayInfo dinfo; + SurfaceComposerClient::getDisplayInfo(0, &dinfo); + const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi; + const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi; + // FIXME: set real values here + const_cast<int&>(android_native_window_t::minSwapInterval) = 1; + const_cast<int&>(android_native_window_t::maxSwapInterval) = 1; + const_cast<uint32_t&>(android_native_window_t::flags) = 0; +} + + +Surface::~Surface() +{ + // this is a client-side operation, the surface is destroyed, unmap + // its buffers in this process. + for (int i=0 ; i<2 ; i++) { + if (mBuffers[i] != 0) { + getBufferMapper().unregisterBuffer(mBuffers[i]->handle); + } + } + + // clear all references and trigger an IPC now, to make sure things + // happen without delay, since these resources are quite heavy. + mClient.clear(); + mSurface.clear(); + IPCThreadState::self()->flushCommands(); +} + +status_t Surface::validate(per_client_cblk_t const* cblk) const +{ + if (mToken<0 || mClient==0) { + LOGE("invalid token (%d, identity=%u) or client (%p)", + mToken, mIdentity, mClient.get()); + return NO_INIT; + } + if (cblk == 0) { + LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity); + return NO_INIT; + } + status_t err = cblk->validate(mToken); + if (err != NO_ERROR) { + LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", + mToken, mIdentity, err, strerror(-err)); + return err; + } + if (mIdentity != uint32_t(cblk->layers[mToken].identity)) { + LOGE("using an invalid surface id=%d, identity=%u should be %d", + mToken, mIdentity, cblk->layers[mToken].identity); + return NO_INIT; + } + return NO_ERROR; +} + + +bool Surface::isSameSurface( + const sp<Surface>& lhs, const sp<Surface>& rhs) { if (lhs == 0 || rhs == 0) return false; return lhs->mSurface->asBinder() == rhs->mSurface->asBinder(); } -void* Surface::heapBase(int i) const +// ---------------------------------------------------------------------------- + +int Surface::setSwapInterval(android_native_window_t* window, int interval) +{ + return 0; +} + +int Surface::dequeueBuffer(android_native_window_t* window, + android_native_buffer_t** buffer) +{ + Surface* self = getSelf(window); + return self->dequeueBuffer(buffer); +} + +int Surface::lockBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + Surface* self = getSelf(window); + return self->lockBuffer(buffer); +} + +int Surface::queueBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + Surface* self = getSelf(window); + return self->queueBuffer(buffer); +} + +// ---------------------------------------------------------------------------- + +status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer) +{ + android_native_buffer_t* out; + status_t err = dequeueBuffer(&out); + *buffer = SurfaceBuffer::getSelf(out); + return err; +} + +status_t Surface::lockBuffer(const sp<SurfaceBuffer>& buffer) +{ + return lockBuffer(buffer.get()); +} + +status_t Surface::queueBuffer(const sp<SurfaceBuffer>& buffer) +{ + return queueBuffer(buffer.get()); +} + +// ---------------------------------------------------------------------------- + +int Surface::dequeueBuffer(android_native_buffer_t** buffer) +{ + // FIXME: dequeueBuffer() needs proper implementation + + Mutex::Autolock _l(mSurfaceLock); + + per_client_cblk_t* const cblk = mClient->mControl; + status_t err = validate(cblk); + if (err != NO_ERROR) + return err; + + SurfaceID index(mToken); + + int32_t backIdx = cblk->lock_layer(size_t(index), + per_client_cblk_t::BLOCKING); + + if (backIdx < 0) + return status_t(backIdx); + + mBackbufferIndex = backIdx; + layer_cblk_t* const lcblk = &(cblk->layers[index]); + + volatile const surface_info_t* const back = lcblk->surface + backIdx; + if (back->flags & surface_info_t::eNeedNewBuffer) { + getBufferLocked(backIdx); + } + + const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]); + mDirtyRegion.set(backBuffer->width, backBuffer->height); + *buffer = backBuffer.get(); + + return NO_ERROR; +} + +int Surface::lockBuffer(android_native_buffer_t* buffer) +{ + Mutex::Autolock _l(mSurfaceLock); + + per_client_cblk_t* const cblk = mClient->mControl; + status_t err = validate(cblk); + if (err != NO_ERROR) + return err; + + // FIXME: lockBuffer() needs proper implementation + return 0; +} + +int Surface::queueBuffer(android_native_buffer_t* buffer) +{ + Mutex::Autolock _l(mSurfaceLock); + + per_client_cblk_t* const cblk = mClient->mControl; + status_t err = validate(cblk); + if (err != NO_ERROR) + return err; + + if (mSwapRectangle.isValid()) { + mDirtyRegion.set(mSwapRectangle); + } + + // transmit the dirty region + SurfaceID index(mToken); + layer_cblk_t* const lcblk = &(cblk->layers[index]); + _send_dirty_region(lcblk, mDirtyRegion); + + uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); + if (!(newstate & eNextFlipPending)) + mClient->signalServer(); + + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +status_t Surface::lock(SurfaceInfo* info, bool blocking) { + return Surface::lock(info, NULL, blocking); +} + +status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) { - void* heapBase = mSurfaceHeapBase[i]; - // map lazily so it doesn't get mapped in clients that don't need it - if (heapBase == 0) { - const sp<IMemoryHeap>& heap(mHeap[i]); - if (heap != 0) { - heapBase = static_cast<uint8_t*>(heap->base()); - if (heapBase == MAP_FAILED) { - heapBase = NULL; - LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)", - heap->asBinder().get(), heap.get()); + // FIXME: needs some locking here + + sp<SurfaceBuffer> backBuffer; + status_t err = dequeueBuffer(&backBuffer); + if (err == NO_ERROR) { + err = lockBuffer(backBuffer); + if (err == NO_ERROR) { + // we handle copy-back here... + + const Rect bounds(backBuffer->width, backBuffer->height); + Region scratch(bounds); + Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); + + per_client_cblk_t* const cblk = mClient->mControl; + layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]); + volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex; + if (back->flags & surface_info_t::eBufferDirty) { + // content is meaningless in this case and the whole surface + // needs to be redrawn. + newDirtyRegion.set(bounds); + } else { + newDirtyRegion.andSelf(bounds); + if (!(lcblk->flags & eNoCopyBack)) { + const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]); + const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); + if (!copyback.isEmpty() && frontBuffer!=0) { + // copy front to back + copyBlt(backBuffer, frontBuffer, copyback); + } + } } - mSurfaceHeapBase[i] = heapBase; + mDirtyRegion = newDirtyRegion; + mOldDirtyRegion = newDirtyRegion; + + void* vaddr; + status_t res = backBuffer->lock( + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + newDirtyRegion.bounds(), &vaddr); + + LOGW_IF(res, "failed locking buffer %d (%p)", + mBackbufferIndex, backBuffer->handle); + + mLockedBuffer = backBuffer; + other->w = backBuffer->width; + other->h = backBuffer->height; + other->s = backBuffer->stride; + other->usage = backBuffer->usage; + other->format = backBuffer->format; + other->bits = vaddr; + } + } + return err; +} + +status_t Surface::unlockAndPost() +{ + // FIXME: needs some locking here + + if (mLockedBuffer == 0) + return BAD_VALUE; + + status_t res = mLockedBuffer->unlock(); + LOGW_IF(res, "failed unlocking buffer %d (%p)", + mBackbufferIndex, mLockedBuffer->handle); + + status_t err = queueBuffer(mLockedBuffer); + mLockedBuffer = 0; + return err; +} + +void Surface::_send_dirty_region( + layer_cblk_t* lcblk, const Region& dirty) +{ + const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; + flat_region_t* flat_region = lcblk->region + index; + status_t err = dirty.write(flat_region, sizeof(flat_region_t)); + if (err < NO_ERROR) { + // region doesn't fit, use the bounds + const Region reg(dirty.bounds()); + reg.write(flat_region, sizeof(flat_region_t)); + } +} + +void Surface::setSwapRectangle(const Rect& r) { + mSwapRectangle = r; +} + +status_t Surface::getBufferLocked(int index) +{ + status_t err = NO_MEMORY; + sp<SurfaceBuffer> buffer = mSurface->getBuffer(); + LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL"); + if (buffer != 0) { + sp<SurfaceBuffer>& currentBuffer(mBuffers[index]); + if (currentBuffer != 0) { + getBufferMapper().unregisterBuffer(currentBuffer->handle); + currentBuffer.clear(); + } + err = getBufferMapper().registerBuffer(buffer->handle); + LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); + if (err == NO_ERROR) { + currentBuffer = buffer; } } - return heapBase; + return err; } }; // namespace android diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp index 8acd2ee..025bf6e 100644 --- a/libs/ui/SurfaceComposerClient.cpp +++ b/libs/ui/SurfaceComposerClient.cpp @@ -29,27 +29,21 @@ #include <utils/Errors.h> #include <utils/threads.h> #include <utils/KeyedVector.h> -#include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/IMemory.h> #include <utils/Log.h> +#include <ui/DisplayInfo.h> #include <ui/ISurfaceComposer.h> #include <ui/ISurfaceFlingerClient.h> #include <ui/ISurface.h> #include <ui/SurfaceComposerClient.h> -#include <ui/DisplayInfo.h> #include <ui/Rect.h> -#include <ui/Point.h> #include <private/ui/SharedState.h> #include <private/ui/LayerState.h> #include <private/ui/SurfaceFlingerSynchro.h> -#include <pixelflinger/pixelflinger.h> - -#include <binder/BpBinder.h> - #define VERBOSE(...) ((void)0) //#define VERBOSE LOGD @@ -109,50 +103,8 @@ static volatile surface_flinger_cblk_t const * get_cblk() // --------------------------------------------------------------------------- -static void copyBlt(const GGLSurface& dst, - const GGLSurface& src, const Region& reg) -{ - Region::iterator iterator(reg); - if (iterator) { - // NOTE: dst and src must be the same format - Rect r; - const size_t bpp = bytesPerPixel(src.format); - const size_t dbpr = dst.stride * bpp; - const size_t sbpr = src.stride * bpp; - while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - uint8_t* s = src.data + (r.left + src.stride * r.top) * bpp; - uint8_t* d = dst.data + (r.left + dst.stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); - } - } - } -} - -// --------------------------------------------------------------------------- - -surface_flinger_cblk_t::surface_flinger_cblk_t() -{ -} - -// --------------------------------------------------------------------------- - -per_client_cblk_t::per_client_cblk_t() -{ -} - // these functions are used by the clients -inline status_t per_client_cblk_t::validate(size_t i) const { +status_t per_client_cblk_t::validate(size_t i) const { if (uint32_t(i) >= NUM_LAYERS_MAX) return BAD_INDEX; if (layers[i].swapState & eInvalidSurface) @@ -248,8 +200,9 @@ int32_t per_client_cblk_t::lock_layer(size_t i, uint32_t flags) index = (state&eIndex) ^ ((state&eFlipRequested)>>1); // make sure this buffer is valid - if (layer->surface[index].bits_offset < 0) { - return status_t(layer->surface[index].bits_offset); + status_t err = layer->surface[index].status; + if (err < 0) { + return err; } if (inspect) { @@ -273,7 +226,7 @@ done: uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) { - // atomically set eFlipRequested and clear eLocked and optionnaly + // atomically set eFlipRequested and clear eLocked and optionally // set eNextFlipPending if eFlipRequested was already set layer_cblk_t * const layer = layers + i; @@ -290,7 +243,7 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) if (oldvalue & eFlipRequested) newvalue |= eNextFlipPending; - // if eFlipRequested was alread set, set eNextFlipPending + // if eFlipRequested was already set, set eNextFlipPending } while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState))); @@ -298,9 +251,9 @@ uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i) int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift), int(newvalue)); - // from this point, the server can kick in at anytime and use the first + // from this point, the server can kick in at any time and use the first // buffer, so we cannot use it anymore, and we must use the 'other' - // buffer instead (or wait if it is not availlable yet, see lock_layer). + // buffer instead (or wait if it is not available yet, see lock_layer). return newvalue; } @@ -376,32 +329,6 @@ status_t SurfaceComposerClient::initCheck() const return mStatus; } -status_t SurfaceComposerClient::validateSurface( - per_client_cblk_t const* cblk, Surface const * surface) -{ - SurfaceID index = surface->ID(); - if (cblk == 0) { - LOGE("cblk is null (surface id=%d, identity=%u)", - index, surface->getIdentity()); - return NO_INIT; - } - - status_t err = cblk->validate(index); - if (err != NO_ERROR) { - LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)", - index, surface->getIdentity(), err, strerror(-err)); - return err; - } - - if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) { - LOGE("using an invalid surface id=%d, identity=%u should be %d", - index, surface->getIdentity(), cblk->layers[index].identity); - return NO_INIT; - } - - return NO_ERROR; -} - sp<IBinder> SurfaceComposerClient::connection() const { return (mClient != 0) ? mClient->asBinder() : 0; @@ -439,7 +366,6 @@ void SurfaceComposerClient::dispose() sp<IMemory> controlMemory; sp<ISurfaceFlingerClient> client; - sp<IMemoryHeap> surfaceHeap; { Mutex::Autolock _lg(gLock); @@ -462,9 +388,7 @@ void SurfaceComposerClient::dispose() delete mPrebuiltLayerState; mPrebuiltLayerState = 0; controlMemory = mControlMemory; - surfaceHeap = mSurfaceHeap; mControlMemory.clear(); - mSurfaceHeap.clear(); mControl = 0; mStatus = NO_INIT; } @@ -528,7 +452,13 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays() return n; } -sp<Surface> SurfaceComposerClient::createSurface( + +void SurfaceComposerClient::signalServer() +{ + mSignalServer->signal(); +} + +sp<SurfaceControl> SurfaceComposerClient::createSurface( int pid, DisplayID display, uint32_t w, @@ -536,14 +466,14 @@ sp<Surface> SurfaceComposerClient::createSurface( PixelFormat format, uint32_t flags) { - sp<Surface> result; + sp<SurfaceControl> result; if (mStatus == NO_ERROR) { ISurfaceFlingerClient::surface_data_t data; sp<ISurface> surface = mClient->createSurface(&data, pid, display, w, h, format, flags); if (surface != 0) { if (uint32_t(data.token) < NUM_LAYERS_MAX) { - result = new Surface(this, surface, data, w, h, format, flags); + result = new SurfaceControl(this, surface, data, w, h, format, flags); } } } @@ -568,186 +498,6 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid) return err; } -status_t SurfaceComposerClient::nextBuffer(Surface* surface, - Surface::SurfaceInfo* info) -{ - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = surface->mBackbufferIndex; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const front = lcblk->surface + (1-backIdx); - info->w = front->w; - info->h = front->h; - info->format = front->format; - info->base = surface->heapBase(1-backIdx); - info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset); - info->bpr = front->bpr; - - return 0; -} - -status_t SurfaceComposerClient::lockSurface( - Surface* surface, - Surface::SurfaceInfo* other, - Region* dirty, - bool blocking) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - int32_t backIdx = cblk->lock_layer(size_t(index), - per_client_cblk_t::BLOCKING); - if (backIdx >= 0) { - surface->mBackbufferIndex = backIdx; - layer_cblk_t* const lcblk = &(cblk->layers[index]); - const surface_info_t* const back = lcblk->surface + backIdx; - const surface_info_t* const front = lcblk->surface + (1-backIdx); - other->w = back->w; - other->h = back->h; - other->format = back->format; - other->base = surface->heapBase(backIdx); - other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset); - other->bpr = back->bpr; - - const Rect bounds(other->w, other->h); - Region newDirtyRegion; - - if (back->flags & surface_info_t::eBufferDirty) { - /* it is safe to write *back here, because we're guaranteed - * SurfaceFlinger is not touching it (since it just granted - * access to us) */ - const_cast<surface_info_t*>(back)->flags &= - ~surface_info_t::eBufferDirty; - - // content is meaningless in this case and the whole surface - // needs to be redrawn. - - newDirtyRegion.set(bounds); - if (dirty) { - *dirty = newDirtyRegion; - } - - //if (bytesPerPixel(other->format) == 4) { - // android_memset32( - // (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr); - //} else { - // android_memset16( // fill with green - // (uint16_t*)other->bits, 0x7E0, other->h * other->bpr); - //} - } - else - { - if (dirty) { - dirty->andSelf(Region(bounds)); - newDirtyRegion = *dirty; - } else { - newDirtyRegion.set(bounds); - } - - Region copyback; - if (!(lcblk->flags & eNoCopyBack)) { - const Region previousDirtyRegion(surface->dirtyRegion()); - copyback = previousDirtyRegion.subtract(newDirtyRegion); - } - - if (!copyback.isEmpty()) { - // copy front to back - GGLSurface cb; - cb.version = sizeof(GGLSurface); - cb.width = back->w; - cb.height = back->h; - cb.stride = back->stride; - cb.data = (GGLubyte*)surface->heapBase(backIdx); - cb.data += back->bits_offset; - cb.format = back->format; - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = front->w; - t.height = front->h; - t.stride = front->stride; - t.data = (GGLubyte*)surface->heapBase(1-backIdx); - t.data += front->bits_offset; - t.format = front->format; - - //const Region copyback(lcblk->region + 1-backIdx); - copyBlt(cb, t, copyback); - } - } - - // update dirty region - surface->setDirtyRegion(newDirtyRegion); - } - return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR); -} - -void SurfaceComposerClient::_signal_server() -{ - mSignalServer->signal(); -} - -void SurfaceComposerClient::_send_dirty_region( - layer_cblk_t* lcblk, const Region& dirty) -{ - const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift; - flat_region_t* flat_region = lcblk->region + index; - status_t err = dirty.write(flat_region, sizeof(flat_region_t)); - if (err < NO_ERROR) { - // region doesn't fit, use the bounds - const Region reg(dirty.bounds()); - reg.write(flat_region, sizeof(flat_region_t)); - } -} - -status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - Region dirty(surface->dirtyRegion()); - const Rect& swapRect(surface->swapRectangle()); - if (swapRect.isValid()) { - dirty.set(swapRect); - } - - // transmit the dirty region - layer_cblk_t* const lcblk = &(cblk->layers[index]); - _send_dirty_region(lcblk, dirty); - uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); - if (!(newstate & eNextFlipPending)) - _signal_server(); - return NO_ERROR; -} - -status_t SurfaceComposerClient::unlockSurface(Surface* surface) -{ - Mutex::Autolock _l(surface->getLock()); - - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface); - if (err != NO_ERROR) - return err; - - layer_cblk_t* const lcblk = &(cblk->layers[index]); - cblk->unlock_layer(size_t(index)); - return NO_ERROR; -} - void SurfaceComposerClient::openGlobalTransaction() { Mutex::Autolock _l(gLock); @@ -866,14 +616,8 @@ status_t SurfaceComposerClient::closeTransaction() return NO_ERROR; } -layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) +layer_state_t* SurfaceComposerClient::_get_state_l(SurfaceID index) { - SurfaceID index = surface->ID(); - per_client_cblk_t* const cblk = mControl; - status_t err = validateSurface(cblk, surface.get()); - if (err != NO_ERROR) - return 0; - // API usage error, do nothing. if (mTransactionOpen<=0) { LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d", @@ -892,11 +636,11 @@ layer_state_t* SurfaceComposerClient::_get_state_l(const sp<Surface>& surface) return mStates.editArray() + i; } -layer_state_t* SurfaceComposerClient::_lockLayerState(const sp<Surface>& surface) +layer_state_t* SurfaceComposerClient::_lockLayerState(SurfaceID id) { layer_state_t* s; mLock.lock(); - s = _get_state_l(surface); + s = _get_state_l(id); if (!s) mLock.unlock(); return s; } @@ -906,9 +650,9 @@ void SurfaceComposerClient::_unlockLayerState() mLock.unlock(); } -status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t y) +status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::ePositionChanged; s->x = x; @@ -917,9 +661,9 @@ status_t SurfaceComposerClient::setPosition(Surface* surface, int32_t x, int32_t return NO_ERROR; } -status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h) +status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eSizeChanged; s->w = w; @@ -928,9 +672,9 @@ status_t SurfaceComposerClient::setSize(Surface* surface, uint32_t w, uint32_t h return NO_ERROR; } -status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) +status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eLayerChanged; s->z = z; @@ -938,32 +682,32 @@ status_t SurfaceComposerClient::setLayer(Surface* surface, int32_t z) return NO_ERROR; } -status_t SurfaceComposerClient::hide(Surface* surface) +status_t SurfaceComposerClient::hide(SurfaceID id) { - return setFlags(surface, ISurfaceComposer::eLayerHidden, + return setFlags(id, ISurfaceComposer::eLayerHidden, ISurfaceComposer::eLayerHidden); } -status_t SurfaceComposerClient::show(Surface* surface, int32_t) +status_t SurfaceComposerClient::show(SurfaceID id, int32_t) { - return setFlags(surface, 0, ISurfaceComposer::eLayerHidden); + return setFlags(id, 0, ISurfaceComposer::eLayerHidden); } -status_t SurfaceComposerClient::freeze(Surface* surface) +status_t SurfaceComposerClient::freeze(SurfaceID id) { - return setFlags(surface, ISurfaceComposer::eLayerFrozen, + return setFlags(id, ISurfaceComposer::eLayerFrozen, ISurfaceComposer::eLayerFrozen); } -status_t SurfaceComposerClient::unfreeze(Surface* surface) +status_t SurfaceComposerClient::unfreeze(SurfaceID id) { - return setFlags(surface, 0, ISurfaceComposer::eLayerFrozen); + return setFlags(id, 0, ISurfaceComposer::eLayerFrozen); } -status_t SurfaceComposerClient::setFlags(Surface* surface, +status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags, uint32_t mask) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eVisibilityChanged; s->flags &= ~mask; @@ -973,11 +717,10 @@ status_t SurfaceComposerClient::setFlags(Surface* surface, return NO_ERROR; } - status_t SurfaceComposerClient::setTransparentRegionHint( - Surface* surface, const Region& transparentRegion) + SurfaceID id, const Region& transparentRegion) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eTransparentRegionChanged; s->transparentRegion = transparentRegion; @@ -985,9 +728,9 @@ status_t SurfaceComposerClient::setTransparentRegionHint( return NO_ERROR; } -status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) +status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eAlphaChanged; s->alpha = alpha; @@ -996,11 +739,11 @@ status_t SurfaceComposerClient::setAlpha(Surface* surface, float alpha) } status_t SurfaceComposerClient::setMatrix( - Surface* surface, + SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy ) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eMatrixChanged; layer_state_t::matrix22_t matrix; @@ -1013,9 +756,9 @@ status_t SurfaceComposerClient::setMatrix( return NO_ERROR; } -status_t SurfaceComposerClient::setFreezeTint(Surface* surface, uint32_t tint) +status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) { - layer_state_t* s = _lockLayerState(surface); + layer_state_t* s = _lockLayerState(id); if (!s) return BAD_INDEX; s->what |= ISurfaceComposer::eFreezeTintChanged; s->tint = tint; diff --git a/libs/ui/SurfaceFlingerSynchro.cpp b/libs/ui/SurfaceFlingerSynchro.cpp index 2e8fa12..c81db71 100644 --- a/libs/ui/SurfaceFlingerSynchro.cpp +++ b/libs/ui/SurfaceFlingerSynchro.cpp @@ -14,19 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "SurfaceFlingerSynchro" - #include <stdint.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <binder/IPCThreadState.h> -#include <utils/Log.h> #include <private/ui/SurfaceFlingerSynchro.h> @@ -34,61 +22,10 @@ namespace android { // --------------------------------------------------------------------------- -SurfaceFlingerSynchro::Barrier::Barrier() - : state(CLOSED) { -} - -SurfaceFlingerSynchro::Barrier::~Barrier() { -} - -void SurfaceFlingerSynchro::Barrier::open() { - asm volatile ("":::"memory"); - Mutex::Autolock _l(lock); - state = OPENED; - cv.broadcast(); -} - -void SurfaceFlingerSynchro::Barrier::close() { - Mutex::Autolock _l(lock); - state = CLOSED; -} - -void SurfaceFlingerSynchro::Barrier::waitAndClose() -{ - Mutex::Autolock _l(lock); - while (state == CLOSED) { - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - cv.wait(lock); - } - state = CLOSED; -} - -status_t SurfaceFlingerSynchro::Barrier::waitAndClose(nsecs_t timeout) -{ - Mutex::Autolock _l(lock); - while (state == CLOSED) { - // we're about to wait, flush the binder command buffer - IPCThreadState::self()->flushCommands(); - int err = cv.waitRelative(lock, timeout); - if (err != 0) - return err; - } - state = CLOSED; - return NO_ERROR; -} - -// --------------------------------------------------------------------------- - SurfaceFlingerSynchro::SurfaceFlingerSynchro(const sp<ISurfaceComposer>& flinger) : mSurfaceComposer(flinger) { } - -SurfaceFlingerSynchro::SurfaceFlingerSynchro() -{ -} - SurfaceFlingerSynchro::~SurfaceFlingerSynchro() { } @@ -99,24 +36,6 @@ status_t SurfaceFlingerSynchro::signal() return NO_ERROR; } -status_t SurfaceFlingerSynchro::wait() -{ - mBarrier.waitAndClose(); - return NO_ERROR; -} - -status_t SurfaceFlingerSynchro::wait(nsecs_t timeout) -{ - if (timeout == 0) - return SurfaceFlingerSynchro::wait(); - return mBarrier.waitAndClose(timeout); -} - -void SurfaceFlingerSynchro::open() -{ - mBarrier.open(); -} - // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk new file mode 100644 index 0000000..6cc4a5a --- /dev/null +++ b/libs/ui/tests/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + region.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libui + +LOCAL_MODULE:= test-region + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region.cpp new file mode 100644 index 0000000..0deb2ba --- /dev/null +++ b/libs/ui/tests/region.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "Region" + +#include <stdio.h> +#include <utils/Debug.h> +#include <ui/Rect.h> +#include <ui/Region.h> + +using namespace android; + +int main() +{ + Region reg0( Rect( 0, 0, 100, 100 ) ); + Region reg1 = reg0; + Region reg2, reg3; + + reg0.dump("reg0"); + reg1.dump("reg1"); + + reg0 = reg0 | reg0.translate(150, 0); + reg0.dump("reg0"); + reg1.dump("reg1"); + + reg0 = reg0 | reg0.translate(300, 0); + reg0.dump("reg0"); + reg1.dump("reg1"); + + //reg2 = reg0 | reg0.translate(0, 100); + //reg0.dump("reg0"); + //reg1.dump("reg1"); + //reg2.dump("reg2"); + + //reg3 = reg0 | reg0.translate(0, 150); + //reg0.dump("reg0"); + //reg1.dump("reg1"); + //reg2.dump("reg2"); + //reg3.dump("reg3"); + + LOGD("---"); + reg2 = reg0 | reg0.translate(100, 0); + reg0.dump("reg0"); + reg1.dump("reg1"); + reg2.dump("reg2"); + + return 0; +} + diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 25cfcb8..335b0b0 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -131,6 +131,18 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL /* Interfaces defined by EGL_KHR_image above */ #endif + +#ifndef EGL_ANDROID_swap_rectangle +#define EGL_ANDROID_swap_rectangle 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height); +#endif + + + + #ifdef __cplusplus } #endif diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h index ac00901..9561490 100644 --- a/opengl/include/EGL/eglplatform.h +++ b/opengl/include/EGL/eglplatform.h @@ -89,12 +89,19 @@ typedef Window EGLNativeWindowType; #elif defined(ANDROID) -#include <EGL/eglnatives.h> +struct android_native_window_t; +struct egl_native_pixmap_t; -typedef struct egl_native_window_t* EGLNativeWindowType; +typedef struct android_native_window_t* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; typedef void* EGLNativeDisplayType; +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +struct android_native_buffer_t; +#define EGL_NATIVE_BUFFER_ANDROID 0x6000 /* eglCreateImageKHR target */ +#endif + #else #error "Platform not recognized" #endif diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h index 0924cae..198e679 100644 --- a/opengl/include/GLES/glplatform.h +++ b/opengl/include/GLES/glplatform.h @@ -28,12 +28,6 @@ #define GL_APIENTRY KHRONOS_APIENTRY -// XXX: this should probably not be here -#define GL_DIRECT_TEXTURE_2D_QUALCOMM 0x7E80 - -// XXX: not sure how this is intended to be used -#define GL_GLEXT_PROTOTYPES - #endif #endif /* __glplatform_h_ */ diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h new file mode 100644 index 0000000..0182a67 --- /dev/null +++ b/opengl/include/GLES2/gl2.h @@ -0,0 +1,620 @@ +#ifndef __gl2_h_ +#define __gl2_h_ + +/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */ + +#include <GLES2/gl2platform.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +typedef void GLvoid; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef khronos_int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; + +/* GL types for handling large vertex buffer objects */ +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_2_0 1 + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* AlphaFunction (not supported in ES20) */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* PixelFormat */ +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GL_TEXTURE 0x1702 + +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 + +/* Uniform Types */ +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F + +/* Read Format */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 + +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 + +#define GL_NONE 0 + +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/*------------------------------------------------------------------------- + * GL core functions. + *-----------------------------------------------------------------------*/ + +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode ); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const char* name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source); +GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); +GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const char* name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2_h_ */ diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h new file mode 100644 index 0000000..72f1ae7 --- /dev/null +++ b/opengl/include/GLES2/gl2ext.h @@ -0,0 +1,518 @@ +#ifndef __gl2ext_h_ +#define __gl2ext_h_ + +/* $Revision: 8271 $ on $Date:: 2009-05-21 09:33:40 -0700 #$ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +#ifndef GL_APIENTRYP +# define GL_APIENTRYP GL_APIENTRY* +#endif + +/*------------------------------------------------------------------------* + * OES extension tokens + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_ETC1_RGB8_OES 0x8D64 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#endif + +/* GL_OES_depth_texture */ +/* No new tokens introduced by this extension. */ + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +typedef void* GLeglImageOES; +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE +#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_STENCIL_INDEX1_OES 0x8D46 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_STENCIL_INDEX4_OES 0x8D47 +#endif + +/* GL_OES_texture3D */ +#ifndef GL_OES_texture3D +#define GL_TEXTURE_WRAP_R_OES 0x8072 +#define GL_TEXTURE_3D_OES 0x806F +#define GL_TEXTURE_BINDING_3D_OES 0x806A +#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 +#define GL_SAMPLER_3D_OES 0x8B5F +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 +#endif + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_HALF_FLOAT_OES 0x8D61 +#endif + +/* GL_OES_vertex_half_float */ +/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */ + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 +#define GL_INT_10_10_10_2_OES 0x8DF7 +#endif + +/*------------------------------------------------------------------------* + * AMD extension tokens + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_3DC_X_AMD 0x87F9 +#define GL_3DC_XY_AMD 0x87FA +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_ATC_RGB_AMD 0x8C92 +#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_Z400_BINARY_AMD 0x8740 +#endif + +/* GL_AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_COUNTER_TYPE_AMD 0x8BC0 +#define GL_COUNTER_RANGE_AMD 0x8BC1 +#define GL_UNSIGNED_INT64_AMD 0x8BC2 +#define GL_PERCENTAGE_AMD 0x8BC3 +#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 +#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 +#define GL_PERFMON_RESULT_AMD 0x8BC6 +#endif + +/*------------------------------------------------------------------------* + * EXT extension tokens + *------------------------------------------------------------------------*/ + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_BGRA 0x80E1 +#endif + +/*------------------------------------------------------------------------* + * IMG extension tokens + *------------------------------------------------------------------------*/ + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_BGRA 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 +#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 +#endif + +/*------------------------------------------------------------------------* + * NV extension tokens + *------------------------------------------------------------------------*/ + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#endif + +/*------------------------------------------------------------------------* + * QCOM extension tokens + *------------------------------------------------------------------------*/ + +/* GL_QCOM_driver_control */ +/* No new tokens introduced by this extension. */ + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 +#endif + +/*------------------------------------------------------------------------* + * End of extension tokens, start of corresponding extension functions + *------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------* + * OES extension functions + *------------------------------------------------------------------------*/ + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_OES_compressed_ETC1_RGB8_texture 1 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#endif + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +#define GL_OES_EGL_image 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); +GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); +#endif +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_OES_depth24 1 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_OES_depth32 1 +#endif + +/* GL_OES_depth_texture */ +#ifndef GL_OES_depth_texture +#define GL_OES_depth_texture 1 +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_OES_element_index_uint 1 +#endif + +/* GL_OES_fbo_render_mipmap */ +#ifndef GL_OES_fbo_render_mipmap +#define GL_OES_fbo_render_mipmap 1 +#endif + +/* GL_OES_fragment_precision_high */ +#ifndef GL_OES_fragment_precision_high +#define GL_OES_fragment_precision_high 1 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_OES_get_program_binary +#define GL_OES_get_program_binary 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length); +#endif +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_OES_mapbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); +GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params); +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_OES_packed_depth_stencil 1 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_OES_rgb8_rgba8 1 +#endif + +/* GL_OES_standard_derivatives */ +#ifndef GL_OES_standard_derivatives +#define GL_OES_standard_derivatives 1 +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_OES_stencil1 1 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_OES_stencil4 1 +#endif + +/* GL_OES_texture_3D */ +#ifndef GL_OES_texture_3D +#define GL_OES_texture_3D 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +#endif + +/* GL_OES_texture_float_linear */ +#ifndef GL_OES_texture_float_linear +#define GL_OES_texture_float_linear 1 +#endif + +/* GL_OES_texture_half_float_linear */ +#ifndef GL_OES_texture_half_float_linear +#define GL_OES_texture_half_float_linear 1 +#endif + +/* GL_OES_texture_float */ +#ifndef GL_OES_texture_float +#define GL_OES_texture_float 1 +#endif + +/* GL_OES_texture_half_float */ +#ifndef GL_OES_texture_half_float +#define GL_OES_texture_half_float 1 +#endif + +/* GL_OES_texture_npot */ +#ifndef GL_OES_texture_npot +#define GL_OES_texture_npot 1 +#endif + +/* GL_OES_vertex_half_float */ +#ifndef GL_OES_vertex_half_float +#define GL_OES_vertex_half_float 1 +#endif + +/* GL_OES_vertex_type_10_10_10_2 */ +#ifndef GL_OES_vertex_type_10_10_10_2 +#define GL_OES_vertex_type_10_10_10_2 1 +#endif + +/*------------------------------------------------------------------------* + * AMD extension functions + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_AMD_compressed_3DC_texture 1 +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_AMD_compressed_ATC_texture 1 +#endif + +/* GL_AMD_program_binary_Z400 */ +#ifndef GL_AMD_program_binary_Z400 +#define GL_AMD_program_binary_Z400 1 +#endif + +/* AMD_performance_monitor */ +#ifndef GL_AMD_performance_monitor +#define GL_AMD_performance_monitor 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data); +GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); +GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); +GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); +typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); +typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList); +typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); +typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); +#endif + +/*------------------------------------------------------------------------* + * EXT extension functions + *------------------------------------------------------------------------*/ + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_EXT_texture_type_2_10_10_10_REV 1 +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_EXT_texture_format_BGRA8888 1 +#endif + +/*------------------------------------------------------------------------* + * IMG extension functions + *------------------------------------------------------------------------*/ + +/* GL_IMG_read_format */ +#ifndef GL_IMG_read_format +#define GL_IMG_read_format 1 +#endif + +/* GL_IMG_texture_compression_pvrtc */ +#ifndef GL_IMG_texture_compression_pvrtc +#define GL_IMG_texture_compression_pvrtc 1 +#endif + +/*------------------------------------------------------------------------* + * NV extension functions + *------------------------------------------------------------------------*/ + +/* GL_NV_fence */ +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); +GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); +GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence); +GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence); +GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition); +#endif +typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#endif + +/*------------------------------------------------------------------------* + * QCOM extension functions + *------------------------------------------------------------------------*/ + +/* GL_QCOM_driver_control */ +#ifndef GL_QCOM_driver_control +#define GL_QCOM_driver_control 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); +GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString); +GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); +GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); +#endif +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); +typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString); +typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); +#endif + +/* GL_QCOM_perfmon_global_mode */ +#ifndef GL_QCOM_perfmon_global_mode +#define GL_QCOM_perfmon_global_mode 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __gl2ext_h_ */ diff --git a/opengl/include/GLES2/gl2platform.h b/opengl/include/GLES2/gl2platform.h new file mode 100644 index 0000000..3e9036c --- /dev/null +++ b/opengl/include/GLES2/gl2platform.h @@ -0,0 +1,29 @@ +#ifndef __gl2platform_h_ +#define __gl2platform_h_ + +/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h + * Last modified on 2008/12/19 + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "OpenGL-ES" component "Registry". + */ + +#include <KHR/khrplatform.h> + +#ifndef GL_APICALL +#define GL_APICALL KHRONOS_APICALL +#endif + +#define GL_APIENTRY KHRONOS_APIENTRY + +#endif /* __gl2platform_h_ */ diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk index 3ce0414..060f3c6 100644 --- a/opengl/libagl/Android.mk +++ b/opengl/libagl/Android.mk @@ -6,6 +6,9 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +# Set to 1 to use gralloc and copybits +LIBAGL_USE_GRALLOC_COPYBITS := 1 + LOCAL_SRC_FILES:= \ egl.cpp \ state.cpp \ @@ -32,10 +35,20 @@ ifneq ($(TARGET_SIMULATOR),true) LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif -LOCAL_SHARED_LIBRARIES := libcutils libutils libpixelflinger +ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1) + LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS -I$(LOCAL_PATH)/../../../../hardware/libhardware/modules/gralloc + LOCAL_SRC_FILES += copybit.cpp +endif + +LOCAL_CFLAGS += -DLOG_TAG=\"libagl\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES + +LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger LOCAL_CFLAGS += -fvisibility=hidden LOCAL_LDLIBS := -lpthread -ldl -LOCAL_MODULE:= libagl + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl +LOCAL_MODULE:= libGLES_android include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index ce31854..9deb2cf 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -1,16 +1,16 @@ /* ** Copyright 2006, The Android Open Source Project ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at ** - ** http://www.apache.org/licenses/LICENSE-2.0 + ** http://www.apache.org/licenses/LICENSE-2.0 ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -19,11 +19,13 @@ #include "context.h" #include "TextureObjectManager.h" +#include <private/ui/android_natives_priv.h> + namespace android { // ---------------------------------------------------------------------------- EGLTextureObject::EGLTextureObject() - : mCount(0), mSize(0) + : mSize(0) { init(); } @@ -53,6 +55,10 @@ void EGLTextureObject::init() memset(crop_rect, 0, sizeof(crop_rect)); generate_mipmap = GL_FALSE; direct = GL_FALSE; +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + copybits_fd = -1; +#endif // LIBAGL_USE_GRALLOC_COPYBITS + buffer = 0; } void EGLTextureObject::copyParameters(const sp<EGLTextureObject>& old) @@ -123,6 +129,7 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s) } surface = *s; internalformat = 0; + buffer = 0; // we should keep the crop_rect, but it's delicate because // the new size of the surface could make it invalid. @@ -141,12 +148,26 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s) return NO_ERROR; } +status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer) +{ + GGLSurface sur; + sur.version = sizeof(GGLSurface); + sur.width = native_buffer->width; + sur.height= native_buffer->height; + sur.stride= native_buffer->stride; + sur.format= native_buffer->format; + sur.data = 0; + setSurface(&sur); + buffer = native_buffer; + return NO_ERROR; +} + status_t EGLTextureObject::reallocate( GLint level, int w, int h, int s, int format, int compressedFormat, int bpr) { const size_t size = h * bpr; - if (level == 0) + if (level == 0) { if (size!=mSize || !surface.data) { if (mSize && surface.data) { @@ -177,9 +198,9 @@ status_t EGLTextureObject::reallocate( return NO_MEMORY; } - LOGW_IF(level-1 >= mNumExtraLod, + LOGW_IF(level-1 >= mNumExtraLod, "specifying mipmap level %d, but # of level is %d", - level, mNumExtraLod+1); + level, mNumExtraLod+1); GGLSurface& mipmap = editMip(level); if (mipmap.data) @@ -224,7 +245,7 @@ status_t EGLTextureObject::reallocate( // ---------------------------------------------------------------------------- EGLSurfaceManager::EGLSurfaceManager() - : TokenManager(), mCount(0) + : TokenManager() { } diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index 74ed1a4..e0eadf1 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -1,16 +1,16 @@ /* ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -30,6 +30,7 @@ #include <private/pixelflinger/ggl_context.h> #include <GLES/gl.h> +#include <EGL/egl.h> #include "Tokenizer.h" #include "TokenManager.h" @@ -39,22 +40,20 @@ namespace android { // ---------------------------------------------------------------------------- -class EGLTextureObject +class EGLTextureObject : public LightRefBase<EGLTextureObject> { public: EGLTextureObject(); ~EGLTextureObject(); - // protocol for sp<> - inline void incStrong(const void* id) const; - inline void decStrong(const void* id) const; - inline uint32_t getStrongCount() const; + status_t setSurface(GGLSurface const* s); + status_t setImage(android_native_buffer_t* buffer); + void setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; } - status_t setSurface(GGLSurface const* s); status_t reallocate(GLint level, int w, int h, int s, int format, int compressedFormat, int bpr); - inline size_t size() const; + inline size_t size() const { return mSize; } const GGLSurface& mip(int lod) const; GGLSurface& editMip(int lod); bool hasMipmaps() const { return mMipmaps!=0; } @@ -65,7 +64,6 @@ private: status_t allocateMipmaps(); void freeMipmaps(); void init(); - mutable int32_t mCount; size_t mSize; GGLSurface *mMipmaps; int mNumExtraLod; @@ -81,36 +79,22 @@ public: GLint crop_rect[4]; GLint generate_mipmap; GLint direct; +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + int copybits_fd; +#endif // LIBAGL_USE_GRALLOC_COPYBITS + android_native_buffer_t* buffer; }; -void EGLTextureObject::incStrong(const void* id) const { - android_atomic_inc(&mCount); -} -void EGLTextureObject::decStrong(const void* id) const { - if (android_atomic_dec(&mCount) == 1) { - delete this; - } -} -uint32_t EGLTextureObject::getStrongCount() const { - return mCount; -} -size_t EGLTextureObject::size() const { - return mSize; -} - // ---------------------------------------------------------------------------- -class EGLSurfaceManager : public TokenManager +class EGLSurfaceManager : + public LightRefBase<EGLSurfaceManager>, + public TokenManager { public: EGLSurfaceManager(); ~EGLSurfaceManager(); - // protocol for sp<> - inline void incStrong(const void* id) const; - inline void decStrong(const void* id) const; - typedef void weakref_type; - sp<EGLTextureObject> createTexture(GLuint name); sp<EGLTextureObject> removeTexture(GLuint name); sp<EGLTextureObject> replaceTexture(GLuint name); @@ -118,21 +102,10 @@ public: sp<EGLTextureObject> texture(GLuint name); private: - mutable int32_t mCount; mutable Mutex mLock; KeyedVector< GLuint, sp<EGLTextureObject> > mTextures; }; -void EGLSurfaceManager::incStrong(const void* id) const { - android_atomic_inc(&mCount); -} -void EGLSurfaceManager::decStrong(const void* id) const { - if (android_atomic_dec(&mCount) == 1) { - delete this; - } -} - - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index 8fa7566..6d2cc91 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -1,16 +1,16 @@ -/* +/* ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -26,6 +26,9 @@ #include "primitives.h" #include "texture.h" #include "BufferObjectManager.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "copybit.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS // ---------------------------------------------------------------------------- @@ -250,7 +253,7 @@ static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) { v[2] = GGL_S_TO_X(p[2]); } -typedef array_t::fetcher_t fn_t; +typedef array_t::fetcher_t fn_t; static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x} { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, @@ -334,7 +337,7 @@ void array_t::init( this->bounds = count; } -inline void array_t::resolve() +inline void array_t::resolve() { physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer; } @@ -465,7 +468,7 @@ vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index) // We compute directly the index of a "free" entry from the locked // state of v[2] and v[3]. v = c->vc.vBuffer + 2; - v += v[0].locked | (v[1].locked<<1); + v += v[0].locked | (v[1].locked<<1); } // note: compileElement clears v->flags c->arrays.compileElement(c, v, index); @@ -480,7 +483,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED - vertex_t* const v = c->vc.vCache + + vertex_t* const v = c->vc.vCache + (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1)); if (ggl_likely(v->index == index)) { @@ -491,7 +494,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU - vertex_t* v = c->vc.vCache + + vertex_t* v = c->vc.vCache + (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2; // always record LRU in v[0] @@ -532,12 +535,12 @@ void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE); do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -569,13 +572,13 @@ void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count) count -= 1; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 1); do { - v0 = c->vc.vBuffer + 0; + v0 = c->vc.vBuffer + 0; v = c->vc.vBuffer + 1; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -602,7 +605,7 @@ void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count) return; drawPrimitivesLineStrip(c, first, count); if (ggl_likely(count >= 3)) { - vertex_t* v0 = c->vc.vBuffer; + vertex_t* v0 = c->vc.vBuffer; vertex_t* v1 = c->vc.vBuffer + 1; c->arrays.compileElement(c, v1, first); const uint32_t cc = v0->flags & v1->flags; @@ -617,12 +620,12 @@ void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 2 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -662,14 +665,14 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, // because it allows us to preserve the same winding when the whole // batch is culled. We also need 2 extra vertices in the array, because // we always keep the two first ones. - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2; do { - v0 = c->vc.vBuffer + 0; - v1 = c->vc.vBuffer + 1; + v0 = c->vc.vBuffer + 0; + v1 = c->vc.vBuffer + 1; v = c->vc.vBuffer + 2; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -697,13 +700,19 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, } while (count > 0); } -void drawPrimitivesTriangleStrip(ogles_context_t* c, +void drawPrimitivesTriangleStrip(ogles_context_t* c, GLint first, GLsizei count) { drawPrimitivesTriangleFanOrStrip(c, first, count, 1); } void drawPrimitivesTriangleFan(ogles_context_t* c, GLint first, GLsizei count) { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTrangleFanWithCopybit(c, first, count)) { + return; + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS + drawPrimitivesTriangleFanOrStrip(c, first, count, 2); } @@ -713,12 +722,12 @@ void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 3 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -779,11 +788,11 @@ void drawIndexedPrimitivesLineStrip(ogles_context_t* c, { if (ggl_unlikely(count < 2)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -806,11 +815,11 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, drawIndexedPrimitivesLines(c, count, indices); return; } - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -825,7 +834,7 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, } while (count); v1->locked = 0; - v1 = c->vc.vBuffer; + v1 = c->vc.vBuffer; const uint32_t cc = v0->flags & v1->flags; if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) c->prims.renderLine(c, v0, v1); @@ -861,7 +870,7 @@ static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c, if (ggl_unlikely(count < 3)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1 = v+1; @@ -981,17 +990,17 @@ void compileElements__3x_full(ogles_context_t* c, const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first); const size_t stride = c->arrays.vertex.stride / 4; // const GLfixed* const& m = c->transforms.mvp.matrix.m; - + GLfixed m[16]; memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m)); - + do { const GLfixed rx = vp[0]; const GLfixed ry = vp[1]; const GLfixed rz = vp[2]; vp += stride; v->index = first++; - v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); @@ -1019,7 +1028,7 @@ void compileElements__3x_full(ogles_context_t* c, #pragma mark clippers #endif -static void clipVec4(vec4_t& nv, +static void clipVec4(vec4_t& nv, GLfixed t, const vec4_t& s, const vec4_t& p) { for (int i=0; i<4 ; i++) @@ -1082,10 +1091,10 @@ void validate_arrays(ogles_context_t* c, GLenum mode) // automatically turn it off (in fact we could when the 4th coordinate // is not spcified in the vertex array). // W interpolation is never needed for points. - GLboolean perspective = + GLboolean perspective = c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS); c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective); - + // set anti-aliasing GLboolean smooth = GL_FALSE; switch (mode) { @@ -1116,7 +1125,7 @@ void validate_arrays(ogles_context_t* c, GLenum mode) if (enables & GGL_ENABLE_TMUS) { // needs texture transforms want |= transform_state_t::TEXTURE; } - if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { + if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { want |= transform_state_t::MODELVIEW; // needs eye coords } ogles_validate_transform(c, want); @@ -1135,18 +1144,18 @@ void validate_arrays(ogles_context_t* c, GLenum mode) c->arrays.mv_transform = c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2]; - + /* * *********************************************************************** * pick fetchers * *********************************************************************** */ - + array_machine_t& am = c->arrays; am.vertex.fetch = fetchNop; am.normal.fetch = currentNormal; am.color.fetch = currentColor; - + if (am.vertex.enable) { am.vertex.resolve(); if (am.vertex.bo || am.vertex.pointer) { @@ -1362,9 +1371,18 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) return; // all triangles are culled + validate_arrays(c, mode); + + const uint32_t enables = c->rasterizer.state.enables; + if (enables & GGL_ENABLE_TMUS) + ogles_lock_textures(c); + drawArraysPrims[mode](c, first, count); + if (enables & GGL_ENABLE_TMUS) + ogles_unlock_textures(c); + #if VC_CACHE_STATISTICS c->vc.total = count; c->vc.dump_stats(mode); @@ -1409,15 +1427,23 @@ void glDrawElements( // clear the vertex-cache c->vc.clear(); validate_arrays(c, mode); - + // if indices are in a buffer object, the pointer is treated as an // offset in that buffer. if (c->arrays.element_array_buffer) { indices = c->arrays.element_array_buffer->data + uintptr_t(indices); } + const uint32_t enables = c->rasterizer.state.enables; + if (enables & GGL_ENABLE_TMUS) + ogles_lock_textures(c); + drawElementsPrims[mode](c, count, indices); + + if (enables & GGL_ENABLE_TMUS) + ogles_unlock_textures(c); + #if VC_CACHE_STATISTICS c->vc.total = count; c->vc.dump_stats(mode); @@ -1444,7 +1470,7 @@ void glBindBuffer(GLenum target, GLuint buffer) return; } } - ((target == GL_ARRAY_BUFFER) ? + ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer) = bo; } @@ -1463,7 +1489,7 @@ void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usa ogles_error(c, GL_INVALID_ENUM); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1493,7 +1519,7 @@ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvo ogles_error(c, GL_INVALID_VALUE); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1541,7 +1567,7 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers) } } } - } + } c->bufferObjectManager->deleteBuffers(n, buffers); c->bufferObjectManager->recycleTokens(n, buffers); } diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp new file mode 100644 index 0000000..427e42a --- /dev/null +++ b/opengl/libagl/copybit.cpp @@ -0,0 +1,370 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <stdlib.h> +#include <stdio.h> + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" +#include "primitives.h" +#include "texture.h" +#include "BufferObjectManager.h" + +#include "TextureObjectManager.h" +#include <hardware/gralloc.h> +#include <hardware/copybit.h> +#include "gralloc_priv.h" + +// ---------------------------------------------------------------------------- + +namespace android { + +static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) { + img->w = surface->stride; + img->h = surface->height; + img->format = surface->format; + img->offset = 0; + img->base = surface->data; + img->fd = fd; +} + +struct clipRectRegion : public copybit_region_t { + clipRectRegion(ogles_context_t* c) { + next = iterate; + int x = c->viewport.scissor.x; + int y = c->viewport.scissor.y; + r.l = x; + r.t = y; + r.r = x + c->viewport.scissor.w; + r.b = y + c->viewport.scissor.h; + firstTime = true; + } +private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { + clipRectRegion* myself = (clipRectRegion*) self; + if (myself->firstTime) { + myself->firstTime = false; + *rect = myself->r; + return 1; + } + return 0; + } + mutable copybit_rect_t r; + mutable bool firstTime; +}; + +static bool supportedCopybitsFormat(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_RGB_565: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + case COPYBIT_FORMAT_YCbCr_422_SP: + case COPYBIT_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} + +static bool hasAlpha(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + return true; + default: + return false; + } +} + +static inline int fixedToByte(GGLfixed val) { + return (val - (val >> 8)) >> 8; +} + +/** + * Performs a quick check of the rendering state. If this function returns + * false we cannot use the copybit driver. + */ + +static bool checkContext(ogles_context_t* c) { + + // By convenction copybitQuickCheckContext() has already returned true. + // avoid checking the same information again. + + if (c->copybits.blitEngine == NULL + || (c->rasterizer.state.enables + & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) { + return false; + } + + // Note: The drawSurfaceFd is only set for destination + // surfaces types that are supported by the hardware and + // do not have an alpha channel. So we don't have to re-check that here. + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + if (!supportedCopybitsFormat(textureObject->surface.format)) { + return false; + } + return true; +} + + +static bool copybit(GLint x, GLint y, + GLint w, GLint h, + EGLTextureObject* textureObject, + const GLint* crop_rect, + int transform, + ogles_context_t* c) +{ + // We assume checkContext has already been called and has already + // returned true. + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + + y = cbSurface.height - (y + h); + + const GLint Ucr = crop_rect[0]; + const GLint Vcr = crop_rect[1]; + const GLint Wcr = crop_rect[2]; + const GLint Hcr = crop_rect[3]; + + int32_t dsdx = (Wcr << 16) / w; // dsdx = ((Wcr/w)/Wt)*Wt + int32_t dtdy = ((-Hcr) << 16) / h; // dtdy = -((Hcr/h)/Ht)*Ht + + if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale + || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { + // The requested scale is out of the range the hardware + // can support. + return false; + } + + int32_t texelArea = gglMulx(dtdy, dsdx); + if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) { + // Non-linear filtering on a texture enlargement. + return false; + } + + if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) { + // Non-linear filtering on an texture shrink. + return false; + } + + const uint32_t enables = c->rasterizer.state.enables; + int planeAlpha = 255; + static const int tmu = 0; + texture_t& tev(c->rasterizer.state.texture[tmu]); + bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format); + switch (tev.env) { + + case GGL_REPLACE: + if (!srcTextureHasAlpha) { + planeAlpha = fixedToByte(c->currentColorClamped.a); + } + break; + + case GGL_MODULATE: + if (! (c->currentColorClamped.r == FIXED_ONE + && c->currentColorClamped.g == FIXED_ONE + && c->currentColorClamped.b == FIXED_ONE)) { + return false; + } + planeAlpha = fixedToByte(c->currentColorClamped.a); + break; + + default: + // Incompatible texture environment. + return false; + } + + bool blending = false; + + if ((enables & GGL_ENABLE_BLENDING) + && !(c->rasterizer.state.blend.src == GL_ONE + && c->rasterizer.state.blend.dst == GL_ZERO)) { + // Blending is OK if it is + // the exact kind of blending that the copybits hardware supports. + // Note: The hardware only supports + // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA, + // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA. + // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case, + // because the performance is worth it, even if the results are + // not correct. + if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA + || c->rasterizer.state.blend.src == GL_ONE) + && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA + && c->rasterizer.state.blend.alpha_separate == 0)) { + // Incompatible blend mode. + return false; + } + blending = true; + } else { + // No blending is OK if we are not using alpha. + if (srcTextureHasAlpha || planeAlpha != 255) { + // Incompatible alpha + return false; + } + } + + if (srcTextureHasAlpha && planeAlpha != 255) { + // Can't do two types of alpha at once. + return false; + } + + // LOGW("calling copybits"); + + copybit_device_t* copybit = c->copybits.blitEngine; + copybit_image_t dst; + textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst); + copybit_rect_t drect = {x, y, x+w, y+h}; + + copybit_image_t src; + textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd, + &src); + copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); + + copybit->set_parameter(copybit, COPYBIT_DITHER, + (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); + + clipRectRegion it(c); + copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + return true; +} + +/* + * Try to draw a triangle fan with copybit, return false if we fail. + */ +bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) { + if (! checkContext(c)) { + return false; + } + + c->arrays.compileElements(c, c->vc.vBuffer, 0, 4); + // Is the result a screen aligned rectangle? + int sx[4]; + int sy[4]; + for (int i = 0; i < 4; i++) { + GLfixed x = c->vc.vBuffer[i].window.x; + GLfixed y = c->vc.vBuffer[i].window.y; + if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) { + return false; + } + sx[i] = x >> 4; + sy[i] = y >> 4; + } + + /* + * This is the pattern we're looking for: + * (2)--(3) + * |\ | + * | \ | + * | \ | + * | \| + * (1)--(0) + * + */ + int dx[4]; + int dy[4]; + for (int i = 0; i < 4; i++) { + int i1 = (i + 1) & 3; + dx[i] = sx[i] - sx[i1]; + dy[i] = sy[i] - sy[i1]; + } + if (dx[1] | dx[3] | dy[0] | dy[2]) { + return false; + } + if (dx[0] != -dx[2] || dy[1] != -dy[3]) { + return false; + } + + int x = sx[1]; + int y = sy[1]; + int w = dx[0]; + int h = dy[3]; + + // We expect the texture coordinates to always be the unit square: + + static const GLfixed kExpectedUV[8] = { + 0, 0, + 0, FIXED_ONE, + FIXED_ONE, FIXED_ONE, + FIXED_ONE, 0 + }; + { + const GLfixed* pExpected = &kExpectedUV[0]; + for (int i = 0; i < 4; i++) { + GLfixed u = c->vc.vBuffer[i].texture[0].x; + GLfixed v = c->vc.vBuffer[i].texture[0].y; + if (u != *pExpected++ || v != *pExpected++) { + return false; + } + } + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + GLint tWidth = textureObject->surface.width; + GLint tHeight = textureObject->surface.height; + GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight}; + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + y = cbSurface.height - (y + h); + + return copybit(x, y, w, h, textureObject, crop_rect, + COPYBIT_TRANSFORM_ROT_90, c); +} + +/* + * Try to drawTexiOESWithCopybit, return false if we fail. + */ + +bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c) +{ + // quickly process empty rects + if ((w|h) <= 0) { + return true; + } + + if (! checkContext(c)) { + return false; + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + return copybit(x, y, w, h, textureObject, textureObject->crop_rect, + 0, c); +} + +} // namespace android + diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h new file mode 100644 index 0000000..1888aee --- /dev/null +++ b/opengl/libagl/copybit.h @@ -0,0 +1,75 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#ifndef ANDROID_OPENGLES_COPYBIT_H +#define ANDROID_OPENGLES_COPYBIT_H + +#include <stdlib.h> + +#include <GLES/gl.h> + +#include "TextureObjectManager.h" +namespace android { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + +bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c); +bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, + GLsizei count); + +inline bool copybitQuickCheckContext(ogles_context_t* c) { + return c->copybits.drawSurfaceFd >= 0 + && c->rasterizer.state.enabled_tmu == 1 + && c->textures.tmu[0].texture->copybits_fd >= 0; +} + +/* + * Tries to draw a drawTexiOES using copybit hardware. + * Returns true if successful. + */ +inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c) { + if (!copybitQuickCheckContext(c)) { + return false; + } + + return drawTexiOESWithCopybit_impl(x, y, z, w, h, c); +} + +/* + * Tries to draw a triangle fan using copybit hardware. + * Returns true if successful. + */ +inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first, + GLsizei count) { + /* + * We are looking for the glDrawArrays call made by SurfaceFlinger. + */ + + if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) { + return false; + } + + return drawTrangleFanWithCopybit_impl(c, first, count); +} + + +#endif // LIBAGL_USE_GRALLOC_COPYBITS + +} // namespace android + +#endif // ANDROID_OPENGLES_COPYBIT_H diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index c44478d..f50257a 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -15,8 +15,6 @@ ** limitations under the License. */ -#define LOG_TAG "EGL" - #include <assert.h> #include <errno.h> #include <stdlib.h> @@ -41,11 +39,17 @@ #include <pixelflinger/format.h> #include <pixelflinger/pixelflinger.h> +#include <private/ui/android_natives_priv.h> + #include "context.h" #include "state.h" #include "texture.h" #include "matrix.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "gralloc_priv.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS + #undef NELEM #define NELEM(x) (sizeof(x)/sizeof(*(x))) @@ -89,9 +93,9 @@ static GLint getError() { struct egl_display_t { egl_display_t() : type(0), initialized(0) { } - + static egl_display_t& get_display(EGLDisplay dpy); - + static EGLBoolean is_valid(EGLDisplay dpy) { return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; } @@ -140,18 +144,20 @@ struct egl_surface_t egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); virtual ~egl_surface_t(); virtual bool isValid() const = 0; - + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; + virtual void connect() {} + virtual void disconnect() {} virtual EGLint getWidth() const = 0; virtual EGLint getHeight() const = 0; - virtual void* getBits() const = 0; virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; virtual EGLBoolean swapBuffers(); + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); protected: GGLSurface depth; }; @@ -185,42 +191,161 @@ EGLint egl_surface_t::getRefreshRate() const { EGLint egl_surface_t::getSwapBehavior() const { return EGL_BUFFER_PRESERVED; } +EGLBoolean egl_surface_t::setSwapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) +{ + return EGL_FALSE; +} // ---------------------------------------------------------------------------- -struct egl_window_surface_t : public egl_surface_t +struct egl_window_surface_v2_t : public egl_surface_t { - egl_window_surface_t( + egl_window_surface_v2_t( EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window); + android_native_window_t* window); - ~egl_window_surface_t(); + ~egl_window_surface_v2_t(); - virtual bool isValid() const { return nativeWindow->magic == 0x600913; } + virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; } virtual EGLBoolean swapBuffers(); virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); - virtual EGLint getWidth() const { return nativeWindow->width; } - virtual EGLint getHeight() const { return nativeWindow->height; } - virtual void* getBits() const; + virtual void connect(); + virtual void disconnect(); + virtual EGLint getWidth() const { return buffer->width; } + virtual EGLint getHeight() const { return buffer->height; } virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); + private: - egl_native_window_t* nativeWindow; + status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); + status_t unlock(android_native_buffer_t* buf); + android_native_window_t* nativeWindow; + android_native_buffer_t* buffer; + android_native_buffer_t* previousBuffer; + gralloc_module_t const* module; + int width; + int height; + void* bits; + GGLFormat const* pixelFormatTable; + + struct Rect { + inline Rect() { }; + inline Rect(int32_t w, int32_t h) + : left(0), top(0), right(w), bottom(h) { } + inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) + : left(l), top(t), right(r), bottom(b) { } + Rect& andSelf(const Rect& r) { + left = max(left, r.left); + top = max(top, r.top); + right = min(right, r.right); + bottom = min(bottom, r.bottom); + return *this; + } + bool isEmpty() const { + return (left>=right || top>=bottom); + } + void dump(char const* what) { + LOGD("%s { %5d, %5d, w=%5d, h=%5d }", + what, left, top, right-left, bottom-top); + } + + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + }; + + struct Region { + inline Region() : count(0) { } + static Region subtract(const Rect& lhs, const Rect& rhs) { + Region reg; + Rect* storage = reg.storage; + if (!lhs.isEmpty()) { + if (lhs.top < rhs.top) { // top rect + storage->left = lhs.left; + storage->top = lhs.top; + storage->right = lhs.right; + storage->bottom = max(lhs.top, rhs.top); + storage++; + } + if (lhs.left < rhs.left) { // left-side rect + storage->left = lhs.left; + storage->top = max(lhs.top, rhs.top); + storage->right = max(lhs.left, rhs.left); + storage->bottom = min(lhs.bottom, rhs.bottom); + storage++; + } + if (lhs.right > rhs.right) { // right-side rect + storage->left = min(lhs.right, rhs.right); + storage->top = max(lhs.top, rhs.top); + storage->right = lhs.right; + storage->bottom = min(lhs.bottom, rhs.bottom); + storage++; + } + if (lhs.bottom > rhs.bottom) { // bottom rect + storage->left = lhs.left; + storage->top = min(lhs.bottom, rhs.bottom); + storage->right = lhs.right; + storage->bottom = lhs.bottom; + storage++; + } + reg.count = storage - reg.storage; + } + return reg; + } + bool isEmpty() const { + return count<=0; + } + ssize_t getRects(Rect const* * rects) const { + *rects = storage; + return count; + } + private: + Rect storage[4]; + ssize_t count; + }; + + void copyBlt( + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Rect* reg, ssize_t count); + + Rect dirtyRegion; + Rect oldDirtyRegion; }; -egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, +egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window) - : egl_surface_t(dpy, config, depthFormat), nativeWindow(window) + android_native_window_t* window) + : egl_surface_t(dpy, config, depthFormat), + nativeWindow(window), buffer(0), previousBuffer(0), module(0), + bits(NULL) { + hw_module_t const* pModule; + hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); + module = reinterpret_cast<gralloc_module_t const*>(pModule); + + pixelFormatTable = gglGetPixelFormatTable(); + + // keep a reference on the window + nativeWindow->common.incRef(&nativeWindow->common); + + // dequeue a buffer + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + + // allocate a corresponding depth-buffer + width = buffer->width; + height = buffer->height; if (depthFormat) { - depth.width = window->width; - depth.height = window->height; + depth.width = width; + depth.height = height; depth.stride = depth.width; // use the width here depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { @@ -228,76 +353,258 @@ egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, return; } } - nativeWindow->incRef(nativeWindow); + + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); +} + +egl_window_surface_v2_t::~egl_window_surface_v2_t() { + if (buffer) { + buffer->common.decRef(&buffer->common); + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + } + nativeWindow->common.decRef(&nativeWindow->common); +} + +void egl_window_surface_v2_t::connect() +{ + // Lock the buffer + nativeWindow->lockBuffer(nativeWindow, buffer); + // pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { + LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); + // FIXME: we should make sure we're not accessing the buffer anymore + } +} + +void egl_window_surface_v2_t::disconnect() +{ + if (buffer) { + bits = NULL; + unlock(buffer); + } +} + +status_t egl_window_surface_v2_t::lock( + android_native_buffer_t* buf, int usage, void** vaddr) +{ + int err = module->lock(module, buf->handle, + usage, 0, 0, buf->width, buf->height, vaddr); + return err; +} + +status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) +{ + int err = module->unlock(module, buf->handle); + return err; } -egl_window_surface_t::~egl_window_surface_t() { - nativeWindow->decRef(nativeWindow); + +void egl_window_surface_v2_t::copyBlt( + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Rect* reg, ssize_t count) +{ + // FIXME: use copybit if possible + // NOTE: dst and src must be the same format + + Rect r; + const size_t bpp = pixelFormatTable[src->format].size; + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + uint8_t const * const src_bits = (uint8_t const *)src_vaddr; + uint8_t * const dst_bits = (uint8_t *)dst_vaddr; + + for (int i= 0 ; i<count ; i++) { + const Rect& r(reg[i]); + ssize_t w = r.right - r.left; + ssize_t h = r.bottom - r.top; + if (w <= 0 || h<=0) continue; + size_t size = w * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); + } } -EGLBoolean egl_window_surface_t::swapBuffers() +EGLBoolean egl_window_surface_v2_t::swapBuffers() { - uint32_t flags = nativeWindow->swapBuffers(nativeWindow); - if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) { + /* + * Handle eglSetSwapRectangleANDROID() + * We copyback from the front buffer + */ + if (!dirtyRegion.isEmpty()) { + dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); + if (previousBuffer) { + const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); + if (!copyBack.isEmpty()) { + Rect const* list; + ssize_t count = copyBack.getRects(&list); + // copy from previousBuffer to buffer + void* prevBits; + if (lock(previousBuffer, + GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) + { + copyBlt(buffer, bits, previousBuffer, prevBits, list, count); + unlock(previousBuffer); + } + } + } + oldDirtyRegion = dirtyRegion; + } + + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + previousBuffer = 0; + } + + unlock(buffer); + previousBuffer = buffer; + nativeWindow->queueBuffer(nativeWindow, buffer); + buffer = 0; + + // dequeue a new buffer + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + nativeWindow->lockBuffer(nativeWindow, buffer); + + // reallocate the depth-buffer if needed + if ((width != buffer->width) || (height != buffer->height)) { // TODO: we probably should reset the swap rect here // if the window size has changed + width = buffer->width; + height = buffer->height; if (depth.data) { free(depth.data); - depth.width = nativeWindow->width; - depth.height = nativeWindow->height; - depth.stride = nativeWindow->stride; + depth.width = width; + depth.height = height; + depth.stride = buffer->stride; depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + setError(EGL_BAD_ALLOC, EGL_FALSE); return EGL_FALSE; } } } + + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); + + // finally pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { + LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); + // FIXME: we should make sure we're not accessing the buffer anymore + } + return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl) +EGLBoolean egl_window_surface_v2_t::setSwapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) +{ + dirtyRegion = Rect(l, t, l+w, t+h); + return EGL_TRUE; +} + +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + +static bool supportedCopybitsDestinationFormat(int format) { + // Hardware supported and no destination alpha + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} +#endif + +EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)bits; + buffer.format = this->buffer->format; gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + gl->copybits.drawSurfaceFd = -1; + if (supportedCopybitsDestinationFormat(buffer.format)) { + buffer_handle_t handle = this->buffer->handle; + if (handle != NULL) { + private_handle_t* hand = private_handle_t::dynamicCast(handle); + if (hand != NULL) { + if (hand->usesPhysicallyContiguousMemory()) { + gl->copybits.drawSurfaceFd = hand->fd; + } + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl) +EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! + buffer.format = this->buffer->format; gl->rasterizer.procs.readBuffer(gl, &buffer); return EGL_TRUE; } -void* egl_window_surface_t::getBits() const { - return (GGLubyte*)nativeWindow->base + nativeWindow->offset; -} -EGLint egl_window_surface_t::getHorizontalResolution() const { +EGLint egl_window_surface_v2_t::getHorizontalResolution() const { return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getVerticalResolution() const { +EGLint egl_window_surface_v2_t::getVerticalResolution() const { return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getRefreshRate() const { - return (nativeWindow->fps * EGL_DISPLAY_SCALING); +EGLint egl_window_surface_v2_t::getRefreshRate() const { + return (60 * EGL_DISPLAY_SCALING); // FIXME } -EGLint egl_window_surface_t::getSwapBehavior() const { - uint32_t flags = nativeWindow->flags; - if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER) - return EGL_BUFFER_DESTROYED; - return EGL_BUFFER_PRESERVED; +EGLint egl_window_surface_v2_t::getSwapBehavior() const +{ + /* + * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves + * the content of the swapped buffer. + * + * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. + * + * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED + * only applies to the area specified by eglSetSwapRectangleANDROID(), that + * is, everything outside of this area is preserved. + * + * This implementation of EGL assumes the later case. + * + */ + + return EGL_BUFFER_DESTROYED; } // ---------------------------------------------------------------------------- @@ -311,12 +618,11 @@ struct egl_pixmap_surface_t : public egl_surface_t virtual ~egl_pixmap_surface_t() { } - virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } + virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return nativePixmap.width; } virtual EGLint getHeight() const { return nativePixmap.height; } - virtual void* getBits() const { return nativePixmap.data; } private: egl_native_pixmap_t nativePixmap; }; @@ -347,7 +653,7 @@ EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) buffer.stride = nativePixmap.stride; buffer.data = nativePixmap.data; buffer.format = nativePixmap.format; - + gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); @@ -376,12 +682,11 @@ struct egl_pbuffer_surface_t : public egl_surface_t virtual ~egl_pbuffer_surface_t(); - virtual bool isValid() const { return pbuffer.data != 0; } + virtual bool isValid() const { return pbuffer.data != 0; } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return pbuffer.width; } virtual EGLint getHeight() const { return pbuffer.height; } - virtual void* getBits() const { return pbuffer.data; } private: GGLSurface pbuffer; }; @@ -407,7 +712,7 @@ egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, pbuffer.stride = w; pbuffer.data = (GGLubyte*)malloc(size); pbuffer.format = f; - + if (depthFormat) { depth.width = pbuffer.width; depth.height = pbuffer.height; @@ -468,7 +773,12 @@ struct config_management_t { static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "1.2 Android Driver"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionsString = ""; +static char const * const gExtensionsString = + "EGL_KHR_image_base " + // "KHR_image_pixmap " + "EGL_ANDROID_image_native_buffer " + "EGL_ANDROID_swap_rectangle " + ; // ---------------------------------------------------------------------------- @@ -496,6 +806,10 @@ static const extention_map_t gExtentionMap[] = { (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, { "glQueryMatrixxOES", (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, + { "glEGLImageTargetTexture2DOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, + { "glEGLImageTargetRenderbufferStorageOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, { "glClipPlanef", (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, { "glClipPlanex", @@ -512,7 +826,7 @@ static const extention_map_t gExtentionMap[] = { (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, }; -/* +/* * In the lists below, attributes names MUST be sorted. * Additionally, all configs must be sorted according to * the EGL specification. @@ -523,7 +837,7 @@ static config_pair_t const config_base_attribute_list[] = { { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, { EGL_LEVEL, 0 }, { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, - { EGL_MAX_PBUFFER_PIXELS, + { EGL_MAX_PBUFFER_PIXELS, GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, { EGL_NATIVE_RENDERABLE, EGL_TRUE }, @@ -660,9 +974,9 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) { while (first <= last) { int mid = (first + last) / 2; - if (key > sortedArray[mid].key) { + if (key > sortedArray[mid].key) { first = mid + 1; - } else if (key < sortedArray[mid].key) { + } else if (key < sortedArray[mid].key) { last = mid - 1; } else { return mid; @@ -674,13 +988,13 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) static int isAttributeMatching(int i, EGLint attr, EGLint val) { // look for the attribute in all of our configs - config_pair_t const* configFound = gConfigs[i].array; + config_pair_t const* configFound = gConfigs[i].array; int index = binarySearch<config_pair_t>( gConfigs[i].array, 0, gConfigs[i].size-1, attr); if (index < 0) { - configFound = config_base_attribute_list; + configFound = config_base_attribute_list; index = binarySearch<config_pair_t>( config_base_attribute_list, 0, NELEM(config_base_attribute_list)-1, @@ -794,28 +1108,28 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -828,9 +1142,9 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, //if (EGLint(info.format) != pixelFormat) // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - egl_surface_t* surface = - new egl_window_surface_t(dpy, config, depthFormat, - static_cast<egl_native_window_t*>(window)); + egl_surface_t* surface; + surface = new egl_window_surface_v2_t(dpy, config, depthFormat, + static_cast<android_native_window_t*>(window)); if (!surface->isValid()) { // there was a problem in the ctor, the error @@ -863,28 +1177,28 @@ static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -916,10 +1230,10 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, EGLint surfaceType; if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE; - + if (!(surfaceType & EGL_PBUFFER_BIT)) return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - + EGLint configID; if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) return EGL_FALSE; @@ -927,28 +1241,28 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -1001,7 +1315,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) egl_display_t& d = egl_display_t::get_display(dpy); d.type = display; return dpy; - } + } return EGL_NO_DISPLAY; } @@ -1009,10 +1323,10 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + EGLBoolean res = EGL_TRUE; egl_display_t& d = egl_display_t::get_display(dpy); - + if (android_atomic_inc(&d.initialized) == 0) { // initialize stuff here if needed //pthread_mutex_lock(&gInitMutex); @@ -1080,7 +1394,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, *num_config = 0; return EGL_TRUE; } - + int numAttributes = 0; int numConfigs = NELEM(gConfigs); uint32_t possibleMatch = (1<<numConfigs)-1; @@ -1161,7 +1475,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, { return createWindowSurface(dpy, config, window, attrib_list); } - + EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) @@ -1174,7 +1488,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, { return createPbufferSurface(dpy, config, attrib_list); } - + EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) @@ -1185,6 +1499,11 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) return setError(EGL_BAD_SURFACE, EGL_FALSE); if (surface->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (surface->ctx) { + // FIXME: this surface is current check what the spec says + surface->disconnect(); + surface->ctx = 0; + } delete surface; } return EGL_TRUE; @@ -1244,7 +1563,7 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface eglSurface, *value = (wr * EGL_DISPLAY_SCALING) / hr; } break; case EGL_SWAP_BEHAVIOR: - *value = surface->getSwapBehavior(); + *value = surface->getSwapBehavior(); break; default: ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); @@ -1294,7 +1613,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } EGLContext current_ctx = EGL_NO_CONTEXT; - + if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) return setError(EGL_BAD_MATCH, EGL_FALSE); @@ -1310,21 +1629,28 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, egl_surface_t* r = (egl_surface_t*)read; if ((d && d->ctx && d->ctx != ctx) || (r && r->ctx && r->ctx != ctx)) { - // once of the surface is bound to a context in another thread + // one of the surface is bound to a context in another thread return setError(EGL_BAD_ACCESS, EGL_FALSE); } } - // TODO: call connect / disconnect on the surface - ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { egl_context_t* c = egl_context_t::context(ctx); egl_surface_t* d = (egl_surface_t*)draw; egl_surface_t* r = (egl_surface_t*)read; - c->read = read; + + if (c->draw) { + reinterpret_cast<egl_surface_t*>(c->draw)->disconnect(); + } + if (c->read) { + // FIXME: unlock/disconnect the read surface too + } + c->draw = draw; + c->read = read; + if (c->flags & egl_context_t::NEVER_CURRENT) { c->flags &= ~egl_context_t::NEVER_CURRENT; GLint w = 0; @@ -1338,10 +1664,12 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, ogles_scissor(gl, 0, 0, w, h); } if (d) { + d->connect(); d->ctx = ctx; d->bindDrawSurface(gl); } if (r) { + // FIXME: lock/connect the read surface too r->ctx = ctx; r->bindReadSurface(gl); } @@ -1352,8 +1680,14 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, egl_context_t* c = egl_context_t::context(current_ctx); egl_surface_t* d = (egl_surface_t*)c->draw; egl_surface_t* r = (egl_surface_t*)c->read; - if (d) d->ctx = EGL_NO_CONTEXT; - if (r) r->ctx = EGL_NO_CONTEXT; + if (d) { + d->ctx = EGL_NO_CONTEXT; + d->disconnect(); + } + if (r) { + r->ctx = EGL_NO_CONTEXT; + // FIXME: unlock/disconnect the read surface too + } } } return EGL_TRUE; @@ -1425,7 +1759,7 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + egl_surface_t* d = static_cast<egl_surface_t*>(draw); if (d->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); @@ -1558,7 +1892,7 @@ EGLSurface eglCreatePbufferFromClientBuffer( } // ---------------------------------------------------------------------------- -// Android extensions +// EGL_EGLEXT_VERSION 3 // ---------------------------------------------------------------------------- void (*eglGetProcAddress (const char *procname))() @@ -1571,3 +1905,80 @@ void (*eglGetProcAddress (const char *procname))() } return NULL; } + +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + if (ctx != EGL_NO_CONTEXT) { + return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); + } + if (target != EGL_NATIVE_BUFFER_ANDROID) { + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + native_buffer->common.incRef(&native_buffer->common); + return (EGLImageKHR)native_buffer; +} + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + native_buffer->common.decRef(&native_buffer->common); + + return EGL_TRUE; +} + +// ---------------------------------------------------------------------------- +// ANDROID extensions +// ---------------------------------------------------------------------------- + +EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, + EGLint left, EGLint top, EGLint width, EGLint height) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl_surface_t* d = static_cast<egl_surface_t*>(draw); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + // post the surface + d->setSwapRectangle(left, top, width, height); + + return EGL_TRUE; +} diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp index 5cbabea..a00f779 100644 --- a/opengl/libagl/state.cpp +++ b/opengl/libagl/state.cpp @@ -2,16 +2,16 @@ ** ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -28,12 +28,16 @@ #include "BufferObjectManager.h" #include "TextureObjectManager.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include <hardware/copybit.h> +#endif // LIBAGL_USE_GRALLOC_COPYBITS + namespace android { // ---------------------------------------------------------------------------- static char const * const gVendorString = "Android"; -static char const * const gRendererString = "Android PixelFlinger 1.0"; +static char const * const gRendererString = "Android PixelFlinger 1.1"; static char const * const gVersionString = "OpenGL ES-CM 1.0"; static char const * const gExtensionsString = "GL_OES_byte_coordinates " // OK @@ -46,9 +50,9 @@ static char const * const gExtensionsString = "GL_OES_query_matrix " // OK // "GL_OES_point_size_array " // TODO // "GL_OES_point_sprite " // TODO + "GL_OES_EGL_image " // OK "GL_ARB_texture_compression " // OK "GL_ARB_texture_non_power_of_two " // OK - "GL_ANDROID_direct_texture " // OK "GL_ANDROID_user_clip_plane " // OK "GL_ANDROID_vertex_buffer_object " // OK "GL_ANDROID_generate_mipmap " // OK @@ -62,13 +66,13 @@ static char const * const gExtensionsString = ogles_context_t *ogles_init(size_t extra) { void* const base = malloc(extra + sizeof(ogles_context_t) + 32); - if (!base) return 0; + if (!base) return 0; ogles_context_t *c = (ogles_context_t *)((ptrdiff_t(base) + extra + 31) & ~0x1FL); memset(c, 0, sizeof(ogles_context_t)); ggl_init_context(&(c->rasterizer)); - + // XXX: this should be passed as an argument sp<EGLSurfaceManager> smgr(new EGLSurfaceManager()); c->surfaceManager = smgr.get(); @@ -87,13 +91,42 @@ ogles_context_t *ogles_init(size_t extra) c->rasterizer.base = base; c->point.size = TRI_ONE; c->line.width = TRI_ONE; - + // in OpenGL, writing to the depth buffer is enabled by default. c->rasterizer.procs.depthMask(c, 1); - + // OpenGL enables dithering by default c->rasterizer.procs.enable(c, GL_DITHER); + c->copybits.blitEngine = NULL; + c->copybits.minScale = 0; + c->copybits.maxScale = 0; + c->copybits.drawSurfaceFd = -1; + +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + hw_module_t const* module; + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + struct copybit_device_t* copyBits; + if (copybit_open(module, ©Bits) == 0) { + c->copybits.blitEngine = copyBits; + { + int minLim = copyBits->get(copyBits, + COPYBIT_MINIFICATION_LIMIT); + if (minLim != -EINVAL && minLim > 0) { + c->copybits.minScale = (1 << 16) / minLim; + } + } + { + int magLim = copyBits->get(copyBits, + COPYBIT_MAGNIFICATION_LIMIT); + if (magLim != -EINVAL && magLim > 0) { + c->copybits.maxScale = min(32*1024-1, magLim) << 16; + } + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS + return c; } @@ -107,7 +140,12 @@ void ogles_uninit(ogles_context_t* c) c->surfaceManager->decStrong(c); c->bufferObjectManager->decStrong(c); ggl_uninit_context(&(c->rasterizer)); - free(c->rasterizer.base); + free(c->rasterizer.base); +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (c->copybits.blitEngine != NULL) { + copybit_close((struct copybit_device_t*) c->copybits.blitEngine); + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS } void _ogles_error(ogles_context_t* c, GLenum error) @@ -188,7 +226,7 @@ static void enable_disable(ogles_context_t* c, GLenum cap, int enabled) // these need to fall through into the rasterizer c->rasterizer.procs.enableDisable(c, cap, enabled); break; - + case GL_MULTISAMPLE: case GL_SAMPLE_ALPHA_TO_COVERAGE: case GL_SAMPLE_ALPHA_TO_ONE: @@ -281,7 +319,7 @@ void glHint(GLenum target, GLenum mode) case GL_LINE_SMOOTH_HINT: break; case GL_POINT_SMOOTH_HINT: - c->rasterizer.procs.enableDisable(c, + c->rasterizer.procs.enableDisable(c, GGL_POINT_SMOOTH_NICE, mode==GL_NICEST); break; case GL_PERSPECTIVE_CORRECTION_HINT: @@ -323,7 +361,7 @@ GLenum glGetError() c->error = 0; return ret; } - + if (c->rasterizer.error) { const GLenum ret(c->rasterizer.error); c->rasterizer.error = 0; @@ -362,25 +400,25 @@ void glGetIntegerv(GLenum pname, GLint *params) int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].ah - formats[index].al; - break; + break; } case GL_RED_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].rh - formats[index].rl; - break; + break; } case GL_GREEN_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].gh - formats[index].gl; - break; + break; } case GL_BLUE_BITS: { int index = c->rasterizer.state.buffers.color.format; GGLFormat const * formats = gglGetPixelFormatTable(); params[0] = formats[index].bh - formats[index].bl; - break; + break; } case GL_COMPRESSED_TEXTURE_FORMATS: params[ 0] = GL_PALETTE4_RGB8_OES; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index b6f534b..d675107 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -2,16 +2,16 @@ ** ** Copyright 2006, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ @@ -23,6 +23,13 @@ #include "texture.h" #include "TextureObjectManager.h" +#include <private/ui/android_natives_priv.h> + +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "copybit.h" +#include "gralloc_priv.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS + namespace android { // ---------------------------------------------------------------------------- @@ -48,7 +55,7 @@ void ogles_init_texture(ogles_context_t* c) // each context has a default named (0) texture (not shared) c->textures.defaultTexture = new EGLTextureObject(); c->textures.defaultTexture->incStrong(c); - + // bind the default texture to each texture unit for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { bindTextureTmu(c, i, 0, c->textures.defaultTexture); @@ -96,7 +103,7 @@ void validate_tmu(ogles_context_t* c, int i) } } -void ogles_validate_texture_impl(ogles_context_t* c) +void ogles_validate_texture(ogles_context_t* c) { for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { if (c->rasterizer.state.texture[i].enable) @@ -110,6 +117,66 @@ void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) { c->textures.tmu[tmu].dirty = flags; } +/* + * If the active textures are EGLImage, they need to be locked before + * they can be used. + * + * FIXME: code below is far from being optimal + * + */ + +void ogles_lock_textures(ogles_context_t* c) +{ + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->rasterizer.state.texture[i].enable) { + texture_unit_t& u(c->textures.tmu[i]); + android_native_buffer_t* native_buffer = u.texture->buffer; + if (native_buffer) { + c->rasterizer.procs.activeTexture(c, i); + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + continue; + + gralloc_module_t const* module = + reinterpret_cast<gralloc_module_t const*>(pModule); + + void* vaddr; + int err = module->lock(module, native_buffer->handle, + GRALLOC_USAGE_SW_READ_OFTEN, + 0, 0, native_buffer->width, native_buffer->height, + &vaddr); + + u.texture->setImageBits(vaddr); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + } + } + } +} + +void ogles_unlock_textures(ogles_context_t* c) +{ + for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { + if (c->rasterizer.state.texture[i].enable) { + texture_unit_t& u(c->textures.tmu[i]); + android_native_buffer_t* native_buffer = u.texture->buffer; + if (native_buffer) { + c->rasterizer.procs.activeTexture(c, i); + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + continue; + + gralloc_module_t const* module = + reinterpret_cast<gralloc_module_t const*>(pModule); + + module->unlock(module, native_buffer->handle); + u.texture->setImageBits(NULL); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + } + } + } + c->rasterizer.procs.activeTexture(c, c->textures.active); +} + // ---------------------------------------------------------------------------- #if 0 #pragma mark - @@ -255,7 +322,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) u.texture->decStrong(c); if (name == 0) { - // 0 is our local texture object, not shared with anyone. + // 0 is our local texture object, not shared with anyone. // But it affects all bound TMUs immediately. // (we need to invalidate all units bound to this texture object) tex = c->textures.defaultTexture; @@ -273,7 +340,7 @@ sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) u.texture = tex.get(); u.texture->incStrong(c); u.name = name; - invalidate_texture(c, active); + invalidate_texture(c, active); return tex; } @@ -282,7 +349,7 @@ void bindTextureTmu( { if (tex.get() == c->textures.tmu[tmu].texture) return; - + // free the reference to the previously bound object texture_unit_t& u(c->textures.tmu[tmu]); if (u.texture) @@ -310,7 +377,7 @@ int createTextureSurface(ogles_context_t* c, if (formatIdx == 0) { // we don't know what to do with this return GL_INVALID_OPERATION; } - + // figure out the size we need as well as the stride const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); const int32_t align = c->textures.unpackAlignment-1; @@ -530,8 +597,8 @@ static void texParameterx( ogles_error(c, GL_INVALID_ENUM); return; } - - EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; + + EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; switch (pname) { case GL_TEXTURE_WRAP_S: if ((param == GL_REPEAT) || @@ -581,13 +648,12 @@ invalid_enum: } -static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, + +static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, ogles_context_t* c) { - // quickly reject empty rects - if ((w|h) <= 0) - return; - + ogles_lock_textures(c); + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = gglIntToFixed(cbSurface.height) - (y + h); w >>= FIXED_BITS; @@ -610,7 +676,7 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); u.dirty = 0xFF; // XXX: should be more subtle - EGLTextureObject* textureObject = u.texture; + EGLTextureObject* textureObject = u.texture; const GLint Ucr = textureObject->crop_rect[0] << 16; const GLint Vcr = textureObject->crop_rect[1] << 16; const GLint Wcr = textureObject->crop_rect[2] << 16; @@ -641,11 +707,30 @@ static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, c->rasterizer.procs.disable(c, GGL_W_LERP); c->rasterizer.procs.disable(c, GGL_AA); c->rasterizer.procs.shadeModel(c, GL_FLAT); - c->rasterizer.procs.recti(c, + c->rasterizer.procs.recti(c, gglFixedToIntRound(x), gglFixedToIntRound(y), gglFixedToIntRound(x)+w, gglFixedToIntRound(y)+h); + + ogles_unlock_textures(c); +} + +static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, + ogles_context_t* c) +{ +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTexiOESWithCopybit(gglFixedToIntRound(x), + gglFixedToIntRound(y), gglFixedToIntRound(z), + gglFixedToIntRound(w), gglFixedToIntRound(h), c)) { + return; + } +#else + // quickly reject empty rects + if ((w|h) <= 0) + return; +#endif + drawTexxOESImp(x, y, z, w, h, c); } static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c) @@ -656,14 +741,21 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte // which is a lot faster. if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTexiOESWithCopybit(x, y, z, w, h, c)) { + return; + } +#endif const int tmu = 0; texture_unit_t& u(c->textures.tmu[tmu]); - EGLTextureObject* textureObject = u.texture; + EGLTextureObject* textureObject = u.texture; const GLint Wcr = textureObject->crop_rect[2]; const GLint Hcr = textureObject->crop_rect[3]; if ((w == Wcr) && (h == -Hcr)) { +#ifndef LIBAGL_USE_GRALLOC_COPYBITS if ((w|h) <= 0) return; // quickly reject empty rects +#endif if (u.dirty) { c->rasterizer.procs.activeTexture(c, tmu); @@ -679,14 +771,14 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); u.dirty = 0xFF; // XXX: should be more subtle c->rasterizer.procs.activeTexture(c, c->textures.active); - + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = cbSurface.height - (y + h); const GLint Ucr = textureObject->crop_rect[0]; const GLint Vcr = textureObject->crop_rect[1]; const GLint s0 = Ucr - x; const GLint t0 = (Vcr + Hcr) - y; - + const GLuint tw = textureObject->surface.width; const GLuint th = textureObject->surface.height; if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) { @@ -694,7 +786,9 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte // in this case, so we just use the slow case, which // at least won't crash goto slow_case; - } + } + + ogles_lock_textures(c); c->rasterizer.procs.texCoord2i(c, s0, t0); const uint32_t enables = c->rasterizer.state.enables; @@ -706,12 +800,15 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte c->rasterizer.procs.disable(c, GGL_AA); c->rasterizer.procs.shadeModel(c, GL_FLAT); c->rasterizer.procs.recti(c, x, y, x+w, y+h); + + ogles_unlock_textures(c); + return; } } slow_case: - drawTexxOES( + drawTexxOESImp( gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z), gglIntToFixed(w), gglIntToFixed(h), c); @@ -749,7 +846,7 @@ void glBindTexture(GLenum target, GLuint texture) } // Bind or create a texture - sp<EGLTextureObject> tex; + sp<EGLTextureObject> tex; if (texture == 0) { // 0 is our local texture object tex = c->textures.defaultTexture; @@ -837,7 +934,7 @@ void glPixelStorei(GLenum pname, GLint param) if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) { ogles_error(c, GL_INVALID_ENUM); return; - } + } if ((param<=0 || param>8) || (param & (param-1))) { ogles_error(c, GL_INVALID_VALUE); return; @@ -945,7 +1042,7 @@ void glCompressedTexImage2D( } // "uncompress" the texture since pixelflinger doesn't support - // any compressed texture format natively. + // any compressed texture format natively. GLenum format; GLenum type; switch (internalformat) { @@ -1009,7 +1106,7 @@ void glTexImage2D( GLenum format, GLenum type, const GLvoid *pixels) { ogles_context_t* c = ogles_context_t::get(); - if (target != GL_TEXTURE_2D && target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { + if (target != GL_TEXTURE_2D) { ogles_error(c, GL_INVALID_ENUM); return; } @@ -1017,7 +1114,7 @@ void glTexImage2D( ogles_error(c, GL_INVALID_VALUE); return; } - if (format != internalformat) { + if (format != (GLenum)internalformat) { ogles_error(c, GL_INVALID_OPERATION); return; } @@ -1027,16 +1124,10 @@ void glTexImage2D( int32_t size = 0; GGLSurface* surface = 0; - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int error = createTextureSurface(c, &surface, &size, - level, format, type, width, height); - if (error) { - ogles_error(c, error); - return; - } - } else if (pixels == 0 || level != 0) { - // pixel can't be null for direct texture - ogles_error(c, GL_INVALID_OPERATION); + int error = createTextureSurface(c, &surface, &size, + level, format, type, width, height); + if (error) { + ogles_error(c, error); return; } @@ -1057,18 +1148,12 @@ void glTexImage2D( userSurface.compressedFormat = 0; userSurface.data = (GLubyte*)pixels; - if (target != GL_DIRECT_TEXTURE_2D_QUALCOMM) { - int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); - if (err) { - ogles_error(c, err); - return; - } - generateMipmap(c, level); - } else { - // bind it to the texture unit - sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); - tex->setSurface(&userSurface); + int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); + if (err) { + ogles_error(c, err); + return; } + generateMipmap(c, level); } } @@ -1143,7 +1228,7 @@ void glTexSubImage2D( int err = copyPixels(c, surface, xoffset, yoffset, - userSurface, 0, 0, width, height); + userSurface, 0, 0, width, height); if (err) { ogles_error(c, err); return; @@ -1196,7 +1281,7 @@ void glCopyTexImage2D( case GL_LUMINANCE_ALPHA: case GL_LUMINANCE: type = GL_UNSIGNED_BYTE; - break; + break; } // figure out the format to use for the new texture @@ -1206,7 +1291,7 @@ void glCopyTexImage2D( case GGL_PIXEL_FORMAT_RGBA_5551: case GGL_PIXEL_FORMAT_RGBA_4444: format = internalformat; - break; + break; case GGL_PIXEL_FORMAT_RGBX_8888: case GGL_PIXEL_FORMAT_RGB_888: case GGL_PIXEL_FORMAT_RGB_565: @@ -1215,7 +1300,7 @@ void glCopyTexImage2D( case GL_LUMINANCE: case GL_RGB: format = internalformat; - break; + break; } break; } @@ -1235,7 +1320,7 @@ void glCopyTexImage2D( ogles_error(c, error); return; } - + // The bottom row is stored first in textures GGLSurface txSurface(*surface); txSurface.stride = -txSurface.stride; @@ -1245,7 +1330,7 @@ void glCopyTexImage2D( int err = copyPixels(c, txSurface, 0, 0, - cbSurface, x, y, cbSurface.width, cbSurface.height); + cbSurface, x, y, cbSurface.width, cbSurface.height); if (err) { ogles_error(c, err); } @@ -1295,7 +1380,7 @@ void glCopyTexSubImage2D( int err = copyPixels(c, surface, xoffset, yoffset, - cbSurface, x, y, width, height); + cbSurface, x, y, width, height); if (err) { ogles_error(c, err); return; @@ -1365,7 +1450,7 @@ void glReadPixels( return; } - ggl->colorBuffer(ggl, &userSurface); // destination is user buffer + ggl->colorBuffer(ggl, &userSurface); // destination is user buffer ggl->bindTexture(ggl, &readSurface); // source is read-buffer ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); ggl->recti(ggl, 0, 0, width, height); @@ -1419,3 +1504,56 @@ void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { ogles_context_t* c = ogles_context_t::get(); drawTexxOES(x, y, z, w, h, c); } + +// ---------------------------------------------------------------------------- +#if 0 +#pragma mark - +#pragma mark EGL Image Extension +#endif + +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + ogles_context_t* c = ogles_context_t::get(); + if (target != GL_TEXTURE_2D) { + ogles_error(c, GL_INVALID_ENUM); + return; + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + if (native_buffer->common.version != sizeof(android_native_buffer_t)) { + ogles_error(c, GL_INVALID_VALUE); + return; + } + + // bind it to the texture unit + sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); + tex->setImage(native_buffer); + + /* + * Here an implementation can retrieve the buffer_handle_t of this buffer + * which gives it access to an arbitrary-defined kernel resource + * (or anything else for that matter). + * There needs to be an intimate knowledge between GLES and buffer_handle_t, + * so make sure to validate the handle before using it. + * Typically, buffer_handle_t comes from the gralloc HAL which is provided + * by the implementor of GLES. + * + */ +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + tex->copybits_fd = -1; + private_handle_t* hand; + if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) { + if (hand->usesPhysicallyContiguousMemory()) { + tex->copybits_fd = hand->fd; + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS +} + +void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ +} diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h index 5c57948..98f7550 100644 --- a/opengl/libagl/texture.h +++ b/opengl/libagl/texture.h @@ -32,13 +32,9 @@ namespace android { void ogles_init_texture(ogles_context_t* c); void ogles_uninit_texture(ogles_context_t* c); -void ogles_validate_texture_impl(ogles_context_t* c); - -inline void ogles_validate_texture(ogles_context_t* c) { - if (c->rasterizer.state.enables & GGL_ENABLE_TMUS) - ogles_validate_texture_impl(c); -} - +void ogles_validate_texture(ogles_context_t* c); +void ogles_lock_textures(ogles_context_t* c); +void ogles_unlock_textures(ogles_context_t* c); }; // namespace android diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk index 02dadbb..33a1698 100644 --- a/opengl/libs/Android.mk +++ b/opengl/libs/Android.mk @@ -1,17 +1,18 @@ LOCAL_PATH:= $(call my-dir) -# +############################################################################### # Build META EGL library # include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - EGL/egl.cpp \ - EGL/gpu.cpp \ + EGL/egl.cpp \ + EGL/hooks.cpp \ + EGL/Loader.cpp \ # -LOCAL_SHARED_LIBRARIES += libcutils libutils libbinder libui +LOCAL_SHARED_LIBRARIES += libcutils libutils LOCAL_LDLIBS := -lpthread -ldl LOCAL_MODULE:= libEGL @@ -23,20 +24,38 @@ else LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif +LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -fvisibility=hidden include $(BUILD_SHARED_LIBRARY) +installed_libEGL := $(LOCAL_INSTALLED_MODULE) +# OpenGL drivers config file +ifneq ($(BOARD_EGL_CFG),) -# -# Build the wrapper OpenGL ES library +include $(CLEAR_VARS) +LOCAL_MODULE := egl.cfg +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl +LOCAL_SRC_FILES := ../../../../$(BOARD_EGL_CFG) +include $(BUILD_PREBUILT) + +# make sure we depend on egl.cfg, so it gets installed +$(installed_libEGL): | egl.cfg + +endif + +############################################################################### +# Build the wrapper OpenGL ES 1.x library # include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ - GLES_CM/gl.cpp.arm \ +LOCAL_SRC_FILES:= \ + GLES_CM/gl.cpp.arm \ # LOCAL_SHARED_LIBRARIES += libcutils libEGL @@ -51,6 +70,37 @@ else LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private endif +LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES +LOCAL_CFLAGS += -fvisibility=hidden + +include $(BUILD_SHARED_LIBRARY) + + +############################################################################### +# Build the wrapper OpenGL ES 2.x library +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + GLES2/gl2.cpp.arm \ +# + +LOCAL_SHARED_LIBRARIES += libcutils libEGL +LOCAL_LDLIBS := -lpthread -ldl +LOCAL_MODULE:= libGLESv2 + +# needed on sim build because of weird logging issues +ifeq ($(TARGET_SIMULATOR),true) +else + LOCAL_SHARED_LIBRARIES += libdl + # we need to access the Bionic private header <bionic_tls.h> + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private +endif + +LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\" +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -fvisibility=hidden include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp new file mode 100644 index 0000000..0e0f2c2 --- /dev/null +++ b/opengl/libs/EGL/Loader.cpp @@ -0,0 +1,278 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <dlfcn.h> +#include <limits.h> + +#include <cutils/log.h> + +#include <EGL/egl.h> + +#include "hooks.h" +#include "egl_impl.h" + +#include "Loader.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + + +/* + * EGL drivers are called + * + * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so + * + */ + +ANDROID_SINGLETON_STATIC_INSTANCE( Loader ) + +// ---------------------------------------------------------------------------- + +Loader::driver_t::driver_t(void* gles) +{ + dso[0] = gles; + for (size_t i=1 ; i<NELEM(dso) ; i++) + dso[i] = 0; +} + +Loader::driver_t::~driver_t() +{ + for (size_t i=0 ; i<NELEM(dso) ; i++) { + if (dso[i]) { + dlclose(dso[i]); + dso[i] = 0; + } + } +} + +status_t Loader::driver_t::set(void* hnd, int32_t api) +{ + switch (api) { + case EGL: + dso[0] = hnd; + break; + case GLESv1_CM: + dso[1] = hnd; + break; + case GLESv2: + dso[2] = hnd; + break; + default: + return BAD_INDEX; + } + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +Loader::entry_t::entry_t(int dpy, int impl, const char* tag) + : dpy(dpy), impl(impl), tag(tag) { +} + +// ---------------------------------------------------------------------------- + +Loader::Loader() +{ + char line[256]; + char tag[256]; + FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r"); + if (cfg == NULL) { + // default config + LOGD("egl.cfg not found, using default config"); + gConfig.add( entry_t(0, 0, "android") ); + } else { + while (fgets(line, 256, cfg)) { + int dpy; + int impl; + if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) { + LOGD(">>> %u %u %s", dpy, impl, tag); + gConfig.add( entry_t(dpy, impl, tag) ); + } + } + fclose(cfg); + } +} + +Loader::~Loader() +{ +} + +const char* Loader::getTag(int dpy, int impl) +{ + const Vector<entry_t>& cfgs(gConfig); + const size_t c = cfgs.size(); + for (size_t i=0 ; i<c ; i++) { + if (dpy == cfgs[i].dpy) + if (impl == cfgs[i].impl) + return cfgs[i].tag.string(); + } + return 0; +} + +void* Loader::open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks) +{ + /* + * TODO: if we don't find display/0, then use 0/0 + * (0/0 should always work) + */ + + void* dso; + char path[PATH_MAX]; + int index = int(display); + driver_t* hnd = 0; + const char* const format = "egl/lib%s_%s.so"; + + char const* tag = getTag(index, impl); + if (tag) { + snprintf(path, PATH_MAX, format, "GLES", tag); + dso = load_driver(path, hooks, EGL | GLESv1_CM | GLESv2); + if (dso) { + hnd = new driver_t(dso); + } else { + // Always load EGL first + snprintf(path, PATH_MAX, "lib%s_%s.so", "EGL", tag); + dso = load_driver(path, hooks, EGL); + if (dso) { + hnd = new driver_t(dso); + + // TODO: make this more automated + snprintf(path, PATH_MAX, format, "GLESv1_CM", tag); + hnd->set( load_driver(path, hooks, GLESv1_CM), GLESv1_CM ); + + snprintf(path, PATH_MAX, format, "GLESv2", tag); + hnd->set( load_driver(path, hooks, GLESv2), GLESv2 ); + } + } + } + + LOG_FATAL_IF(!index && !impl && !hnd, + "couldn't't find the default OpenGL ES implementation " + "for default display"); + + return (void*)hnd; +} + +status_t Loader::close(void* driver) +{ + driver_t* hnd = (driver_t*)driver; + delete hnd; + return NO_ERROR; +} + +void Loader::init_api(void* dso, + char const * const * api, + __eglMustCastToProperFunctionPointerType* curr, + getProcAddressType getProcAddress) +{ + char scrap[256]; + while (*api) { + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); + if (f == NULL) { + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + } + if (f == NULL) { + // Try without the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } + if (f == NULL) { + // Try with the OES postfix + ssize_t index = ssize_t(strlen(name)) - 3; + if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) { + strncpy(scrap, name, index); + scrap[index] = 0; + strcat(scrap, "OES"); + f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); + //LOGD_IF(f, "found <%s> instead", scrap); + } + } + if (f == NULL) { + //LOGD("%s", name); + f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; + } + *curr++ = f; + api++; + } +} + +void *Loader::load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask) +{ + //LOGD("%s", driver); + void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); + LOGE_IF(!dso, + "couldn't load <%s> library (%s)", + driver, dlerror()); + if (dso == 0) + return 0; + + if (mask & EGL) { + getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress"); + + LOGE_IF(!getProcAddress, + "can't find eglGetProcAddress() in %s", driver); + + gl_hooks_t::egl_t* egl = &hooks->egl; + __eglMustCastToProperFunctionPointerType* curr = + (__eglMustCastToProperFunctionPointerType*)egl; + char const * const * api = egl_names; + while (*api) { + char const * name = *api; + __eglMustCastToProperFunctionPointerType f = + (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); + if (f == NULL) { + // couldn't find the entry-point, use eglGetProcAddress() + f = getProcAddress(name); + if (f == NULL) { + f = (__eglMustCastToProperFunctionPointerType)0; + } + } + *curr++ = f; + api++; + } + } + + if (mask & GLESv1_CM) { + init_api(dso, gl_names, + (__eglMustCastToProperFunctionPointerType*)&hooks->gl, + getProcAddress); + } + + if (mask & GLESv2) { + init_api(dso, gl2_names, + (__eglMustCastToProperFunctionPointerType*)&hooks->gl2, + getProcAddress); + } + + return dso; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h new file mode 100644 index 0000000..69f6dd5 --- /dev/null +++ b/opengl/libs/EGL/Loader.h @@ -0,0 +1,90 @@ +/* + ** Copyright 2009, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#ifndef ANDROID_EGL_LOADER_H +#define ANDROID_EGL_LOADER_H + +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include <utils/Errors.h> +#include <utils/Singleton.h> +#include <utils/String8.h> +#include <utils/Vector.h> + +#include <EGL/egl.h> + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +struct gl_hooks_t; + +class Loader : public Singleton<Loader> +{ + friend class Singleton<Loader>; + + typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( + const char*); + + enum { + EGL = 0x01, + GLESv1_CM = 0x02, + GLESv2 = 0x04 + }; + struct driver_t { + driver_t(void* gles); + ~driver_t(); + status_t set(void* hnd, int32_t api); + void* dso[3]; + }; + + struct entry_t { + entry_t() { } + entry_t(int dpy, int impl, const char* tag); + int dpy; + int impl; + String8 tag; + }; + + Vector<entry_t> gConfig; + getProcAddressType getProcAddress; + + const char* getTag(int dpy, int impl); + +public: + ~Loader(); + + void* open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks); + status_t close(void* driver); + +private: + Loader(); + void *load_driver(const char* driver, gl_hooks_t* hooks, uint32_t mask); + + static __attribute__((noinline)) + void init_api(void* dso, + char const * const * api, + __eglMustCastToProperFunctionPointerType* curr, + getProcAddressType getProcAddress); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +#endif /* ANDROID_EGL_LOADER_H */ diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 25e31ee..77648f2 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -14,9 +14,8 @@ ** limitations under the License. */ -#define LOG_TAG "libEGL" - #include <ctype.h> +#include <stdlib.h> #include <string.h> #include <errno.h> #include <dlfcn.h> @@ -37,11 +36,9 @@ #include <cutils/properties.h> #include <cutils/memory.h> -#include <utils/RefBase.h> - #include "hooks.h" #include "egl_impl.h" - +#include "Loader.h" #define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index))) #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) @@ -55,7 +52,15 @@ namespace android { static char const * const gVendorString = "Android"; static char const * const gVersionString = "1.31 Android META-EGL"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionString = ""; +static char const * const gExtensionString = + "EGL_KHR_image " + "EGL_KHR_image_base " + "EGL_KHR_image_pixmap " + "EGL_ANDROID_image_native_buffer " + "EGL_ANDROID_swap_rectangle " + ; + +// ---------------------------------------------------------------------------- template <int MAGIC> struct egl_object_t @@ -87,21 +92,15 @@ struct egl_display_t : public egl_object_t<'_dpy'> struct egl_surface_t : public egl_object_t<'_srf'> { egl_surface_t(EGLDisplay dpy, EGLSurface surface, - NativeWindowType window, int impl, egl_connection_t const* cnx) - : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx) + int impl, egl_connection_t const* cnx) + : dpy(dpy), surface(surface), impl(impl), cnx(cnx) { // NOTE: window must be incRef'ed and connected already } ~egl_surface_t() { - if (window) { - if (window->disconnect) - window->disconnect(window); - window->decRef(window); - } } EGLDisplay dpy; EGLSurface surface; - NativeWindowType window; int impl; egl_connection_t const* cnx; }; @@ -121,6 +120,18 @@ struct egl_context_t : public egl_object_t<'_ctx'> egl_connection_t const* cnx; }; +struct egl_image_t : public egl_object_t<'_img'> +{ + egl_image_t(EGLDisplay dpy, EGLContext context) + : dpy(dpy), context(context) + { + memset(images, 0, sizeof(images)); + } + EGLDisplay dpy; + EGLConfig context; + EGLImageKHR images[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; +}; + struct tls_t { tls_t() : error(EGL_SUCCESS), ctx(0) { } @@ -128,32 +139,6 @@ struct tls_t EGLContext ctx; }; -static void gl_unimplemented() { - LOGE("called unimplemented OpenGL ES API"); -} - -// ---------------------------------------------------------------------------- -// GL / EGL hooks -// ---------------------------------------------------------------------------- - -#undef GL_ENTRY -#undef EGL_ENTRY -#define GL_ENTRY(_r, _api, ...) #_api, -#define EGL_ENTRY(_r, _api, ...) #_api, - -static char const * const gl_names[] = { - #include "gl_entries.in" - #include "glext_entries.in" - NULL -}; - -static char const * const egl_names[] = { - #include "egl_entries.in" - NULL -}; - -#undef GL_ENTRY -#undef EGL_ENTRY // ---------------------------------------------------------------------------- @@ -262,110 +247,8 @@ EGLContext getContext() { return tls->ctx; } - /*****************************************************************************/ -class ISurfaceComposer; -const sp<ISurfaceComposer>& getSurfaceFlinger(); -request_gpu_t* gpu_acquire(void* user); -int gpu_release(void*, request_gpu_t* gpu); - -static __attribute__((noinline)) -void *load_driver(const char* driver, gl_hooks_t* hooks) -{ - //LOGD("%s", driver); - char scrap[256]; - void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); - LOGE_IF(!dso, - "couldn't load <%s> library (%s)", - driver, dlerror()); - - if (dso) { - // first find the symbol for eglGetProcAddress - - typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( - const char*); - - getProcAddressType getProcAddress = - (getProcAddressType)dlsym(dso, "eglGetProcAddress"); - - LOGE_IF(!getProcAddress, - "can't find eglGetProcAddress() in %s", driver); - - __eglMustCastToProperFunctionPointerType* curr; - char const * const * api; - - gl_hooks_t::egl_t* egl = &hooks->egl; - curr = (__eglMustCastToProperFunctionPointerType*)egl; - api = egl_names; - while (*api) { - char const * name = *api; - __eglMustCastToProperFunctionPointerType f = - (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { - // couldn't find the entry-point, use eglGetProcAddress() - f = getProcAddress(name); - if (f == NULL) { - f = (__eglMustCastToProperFunctionPointerType)0; - } - } - *curr++ = f; - api++; - } - - gl_hooks_t::gl_t* gl = &hooks->gl; - curr = (__eglMustCastToProperFunctionPointerType*)gl; - api = gl_names; - while (*api) { - char const * name = *api; - __eglMustCastToProperFunctionPointerType f = - (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); - if (f == NULL) { - // couldn't find the entry-point, use eglGetProcAddress() - f = getProcAddress(name); - } - if (f == NULL) { - // Try without the OES postfix - ssize_t index = ssize_t(strlen(name)) - 3; - if ((index>0 && (index<255)) && (!strcmp(name+index, "OES"))) { - strncpy(scrap, name, index); - scrap[index] = 0; - f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); - //LOGD_IF(f, "found <%s> instead", scrap); - } - } - if (f == NULL) { - // Try with the OES postfix - ssize_t index = ssize_t(strlen(name)) - 3; - if ((index>0 && (index<252)) && (strcmp(name+index, "OES"))) { - strncpy(scrap, name, index); - scrap[index] = 0; - strcat(scrap, "OES"); - f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); - //LOGD_IF(f, "found <%s> instead", scrap); - } - } - if (f == NULL) { - //LOGD("%s", name); - f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; - } - *curr++ = f; - api++; - } - - // hook this driver up with surfaceflinger if needed - register_gpu_t register_gpu = - (register_gpu_t)dlsym(dso, "oem_register_gpu"); - - if (register_gpu != NULL) { - if (getSurfaceFlinger() != 0) { - register_gpu(dso, gpu_acquire, gpu_release); - } - } - } - return dso; -} - template<typename T> static __attribute__((noinline)) int binarySearch( @@ -412,6 +295,14 @@ struct extention_map_t { }; static const extention_map_t gExtentionMap[] = { + { "eglLockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, + { "eglUnlockSurfaceKHR", + (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, + { "eglCreateImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, + { "eglDestroyImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, }; static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; @@ -429,6 +320,12 @@ static void(*findProcAddress(const char* name, // ---------------------------------------------------------------------------- +/* + * To "loose" the GPU, use something like + * gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST]; + * + */ + static int gl_context_lost() { setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); return 0; @@ -491,6 +388,11 @@ egl_context_t* get_context(EGLContext context) { return egl_to_native_cast<egl_context_t>(context); } +static inline +egl_image_t* get_image(EGLImageKHR image) { + return egl_to_native_cast<egl_image_t>(image); +} + static egl_connection_t* validate_display_config( EGLDisplay dpy, EGLConfig config, egl_display_t const*& dp, int& impl, int& index) @@ -540,6 +442,24 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) } +EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image) +{ + EGLContext context = getContext(); + if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR) + return EGL_NO_IMAGE_KHR; + + egl_context_t const * const c = get_context(context); + if (!c->isValid()) + return EGL_NO_IMAGE_KHR; + + egl_image_t const * const i = get_image(image); + if (!i->isValid()) + return EGL_NO_IMAGE_KHR; + + return i->images[c->impl]; +} + + EGLDisplay egl_init_displays(NativeDisplayType display) { if (sEarlyInitState) { @@ -554,12 +474,15 @@ EGLDisplay egl_init_displays(NativeDisplayType display) EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); egl_display_t* d = &gDisplay[index]; + // get our driver loader + Loader& loader(Loader::getInstance()); + // dynamically load all our EGL implementations for that display // and call into the real eglGetGisplay() egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; if (cnx->dso == 0) { cnx->hooks = &gHooks[IMPL_SOFTWARE]; - cnx->dso = load_driver("libagl.so", cnx->hooks); + cnx->dso = loader.open(display, 0, cnx->hooks); } if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) { d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display); @@ -573,7 +496,7 @@ EGLDisplay egl_init_displays(NativeDisplayType display) property_get("debug.egl.hw", value, "1"); if (atoi(value) != 0) { cnx->hooks = &gHooks[IMPL_HARDWARE]; - cnx->dso = load_driver("libhgl.so", cnx->hooks); + cnx->dso = loader.open(display, 1, cnx->hooks); } else { LOGD("3D hardware acceleration is disabled"); } @@ -605,7 +528,8 @@ EGLDisplay egl_init_displays(NativeDisplayType display) if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) { LOGE("h/w accelerated eglGetDisplay() failed (%s)", egl_strerror(cnx->hooks->egl.eglGetError())); - dlclose((void*)cnx->dso); + + loader.close(cnx->dso); cnx->dso = 0; // in case of failure, we want to make sure we don't try again // as it's expensive. @@ -717,6 +641,8 @@ EGLBoolean eglTerminate(EGLDisplay dpy) if (android_atomic_dec(&dp->refs) != 1) return EGL_TRUE; + Loader& loader(Loader::getInstance()); + EGLBoolean res = EGL_FALSE; for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; @@ -732,7 +658,8 @@ EGLBoolean eglTerminate(EGLDisplay dpy) free((void*)dp->queryString[i].extensions); dp->numConfigs[i] = 0; dp->dpys[i] = EGL_NO_DISPLAY; - dlclose((void*)cnx->dso); + + loader.close(cnx->dso); cnx->dso = 0; res = EGL_TRUE; } @@ -909,26 +836,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, int i=0, index=0; egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); if (cnx) { - // window must be connected upon calling underlying - // eglCreateWindowSurface - if (window) { - window->incRef(window); - if (window->connect) - window->connect(window); - } - EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface( dp->dpys[i], dp->configs[i][index], window, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } - - // something went wrong, disconnect and free window - // (will disconnect() automatically) - if (window) { - window->decRef(window); - } } return EGL_NO_SURFACE; } @@ -944,7 +857,7 @@ EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface( dp->dpys[i], dp->configs[i][index], pixmap, attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } } @@ -961,7 +874,7 @@ EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface( dp->dpys[i], dp->configs[i][index], attrib_list); if (surface != EGL_NO_SURFACE) { - egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); + egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); return s; } } @@ -1428,3 +1341,144 @@ EGLSurface eglCreatePbufferFromClientBuffer( } return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); } + +// ---------------------------------------------------------------------------- +// EGL_EGLEXT_VERSION 3 +// ---------------------------------------------------------------------------- + +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + EGLBoolean result = EGL_FALSE; + if (!validate_display_surface(dpy, surface)) + return result; + + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + if (s->cnx->hooks->egl.eglLockSurfaceKHR) { + result = s->cnx->hooks->egl.eglLockSurfaceKHR( + dp->dpys[s->impl], s->surface, attrib_list); + } + return result; +} + +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) +{ + EGLBoolean result = EGL_FALSE; + if (!validate_display_surface(dpy, surface)) + return result; + + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(surface); + + if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) { + result = s->cnx->hooks->egl.eglUnlockSurfaceKHR( + dp->dpys[s->impl], s->surface); + } + return result; +} + +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (ctx != EGL_NO_CONTEXT) { + if (!validate_display_context(dpy, ctx)) + return EGL_NO_IMAGE_KHR; + egl_display_t const * const dp = get_display(dpy); + egl_context_t * const c = get_context(ctx); + // since we have an EGLContext, we know which implementation to use + EGLImageKHR image = c->cnx->hooks->egl.eglCreateImageKHR( + dp->dpys[c->impl], c->context, target, buffer, attrib_list); + if (image == EGL_NO_IMAGE_KHR) + return image; + + egl_image_t* result = new egl_image_t(dpy, ctx); + result->images[c->impl] = image; + return (EGLImageKHR)result; + } else { + // EGL_NO_CONTEXT is a valid parameter + egl_display_t const * const dp = get_display(dpy); + if (dp == 0) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + // since we don't have a way to know which implementation to call, + // we're calling all of them + + EGLImageKHR implImages[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; + bool success = false; + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + implImages[i] = EGL_NO_IMAGE_KHR; + if (cnx->dso) { + if (cnx->hooks->egl.eglCreateImageKHR) { + implImages[i] = cnx->hooks->egl.eglCreateImageKHR( + dp->dpys[i], ctx, target, buffer, attrib_list); + if (implImages[i] != EGL_NO_IMAGE_KHR) { + success = true; + } + } + } + } + if (!success) + return EGL_NO_IMAGE_KHR; + + egl_image_t* result = new egl_image_t(dpy, ctx); + memcpy(result->images, implImages, sizeof(implImages)); + return (EGLImageKHR)result; + } +} + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + egl_display_t const * const dp = get_display(dpy); + if (dp == 0) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + egl_image_t* image = get_image(img); + if (!image->isValid()) { + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + } + + bool success = false; + for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { + egl_connection_t* const cnx = &gEGLImpl[i]; + if (image->images[i] != EGL_NO_IMAGE_KHR) { + if (cnx->dso) { + if (cnx->hooks->egl.eglCreateImageKHR) { + if (cnx->hooks->egl.eglDestroyImageKHR( + dp->dpys[i], image->images[i])) { + success = true; + } + } + } + } + } + if (!success) + return EGL_FALSE; + + delete image; + + return EGL_FALSE; +} + + +// ---------------------------------------------------------------------------- +// ANDROID extensions +// ---------------------------------------------------------------------------- + +EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, + EGLint left, EGLint top, EGLint width, EGLint height) +{ + if (!validate_display_surface(dpy, draw)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(draw); + if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) { + return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl], + s->surface, left, top, width, height); + } + return EGL_FALSE; +} + diff --git a/opengl/libs/egl_entries.in b/opengl/libs/EGL/egl_entries.in index 3b4551b..1fe2b57 100644 --- a/opengl/libs/egl_entries.in +++ b/opengl/libs/EGL/egl_entries.in @@ -50,3 +50,7 @@ EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface) EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) + +/* ANDROID extensions */ + +EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) diff --git a/opengl/libs/EGL/gpu.cpp b/opengl/libs/EGL/gpu.cpp deleted file mode 100644 index 416bd5d..0000000 --- a/opengl/libs/EGL/gpu.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - ** Copyright 2007, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#define LOG_TAG "EGL" - -#include <ctype.h> -#include <string.h> -#include <errno.h> - -#include <sys/ioctl.h> - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - -#include <cutils/log.h> -#include <cutils/properties.h> - -#include <binder/IMemory.h> -#include <utils/threads.h> -#include <binder/IServiceManager.h> -#include <binder/IPCThreadState.h> -#include <binder/Parcel.h> - -#include <ui/EGLDisplaySurface.h> -#include <ui/ISurfaceComposer.h> - -#include "hooks.h" -#include "egl_impl.h" - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -/* - * we provide our own allocators for the GPU regions, these - * allocators go through surfaceflinger - */ - -static Mutex gRegionsLock; -static request_gpu_t gRegions; -static sp<ISurfaceComposer> gSurfaceManager; -GL_API ISurfaceComposer* GLES_localSurfaceManager = 0; - -extern egl_connection_t gEGLImpl[2]; - -const sp<ISurfaceComposer>& getSurfaceFlinger() -{ - Mutex::Autolock _l(gRegionsLock); - - /* - * There is a little bit of voodoo magic here. We want to access - * surfaceflinger for allocating GPU regions, however, when we are - * running as part of surfaceflinger, we want to bypass the - * service manager because surfaceflinger might not be registered yet. - * SurfaceFlinger will populate "GLES_localSurfaceManager" with its - * own address, so we can just use that. - */ - if (gSurfaceManager == 0) { - if (GLES_localSurfaceManager) { - // we're running in SurfaceFlinger's context - gSurfaceManager = GLES_localSurfaceManager; - } else { - // we're a remote process or not part of surfaceflinger, - // go through the service manager - sp<IServiceManager> sm = defaultServiceManager(); - if (sm != NULL) { - sp<IBinder> binder = sm->getService(String16("SurfaceFlinger")); - gSurfaceManager = interface_cast<ISurfaceComposer>(binder); - } - } - } - return gSurfaceManager; -} - -class GPURevokeRequester : public BnGPUCallback -{ -public: - virtual void gpuLost() { - LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger."); - gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST]; - } -}; - -static sp<GPURevokeRequester> gRevokerCallback; - - -request_gpu_t* gpu_acquire(void* user) -{ - sp<ISurfaceComposer> server( getSurfaceFlinger() ); - - Mutex::Autolock _l(gRegionsLock); - if (server == NULL) { - return 0; - } - - ISurfaceComposer::gpu_info_t info; - - if (gRevokerCallback == 0) - gRevokerCallback = new GPURevokeRequester(); - - status_t err = server->requestGPU(gRevokerCallback, &info); - if (err != NO_ERROR) { - LOGD("requestGPU returned %d", err); - return 0; - } - - if (info.regs == 0) { - LOGD("requestGPU() failed"); - return 0; - } - - bool failed = false; - request_gpu_t* gpu = &gRegions; - memset(gpu, 0, sizeof(*gpu)); - - if (info.regs != 0) { - sp<IMemoryHeap> heap(info.regs->getMemory()); - if (heap != 0) { - int fd = heap->heapID(); - gpu->regs.fd = fd; - gpu->regs.base = info.regs->pointer(); - gpu->regs.size = info.regs->size(); - gpu->regs.user = info.regs.get(); -#if HAVE_ANDROID_OS - struct pmem_region region; - if (ioctl(fd, PMEM_GET_PHYS, ®ion) >= 0) - gpu->regs.phys = (void*)region.offset; -#endif - info.regs->incStrong(gpu); - } else { - LOGE("GPU register handle %p is invalid!", info.regs.get()); - failed = true; - } - } - - for (size_t i=0 ; i<info.count && !failed ; i++) { - sp<IMemory>& region(info.regions[i].region); - if (region != 0) { - sp<IMemoryHeap> heap(region->getMemory()); - if (heap != 0) { - const int fd = heap->heapID(); - gpu->gpu[i].fd = fd; - gpu->gpu[i].base = region->pointer(); - gpu->gpu[i].size = region->size(); - gpu->gpu[i].user = region.get(); - gpu->gpu[i].offset = info.regions[i].reserved; -#if HAVE_ANDROID_OS - struct pmem_region reg; - if (ioctl(fd, PMEM_GET_PHYS, ®) >= 0) - gpu->gpu[i].phys = (void*)reg.offset; -#endif - region->incStrong(gpu); - } else { - LOGE("GPU region handle [%d, %p] is invalid!", i, region.get()); - failed = true; - } - } - } - - if (failed) { - // something went wrong, clean up everything! - if (gpu->regs.user) { - static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu); - for (size_t i=0 ; i<info.count ; i++) { - if (gpu->gpu[i].user) { - static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu); - } - } - } - } - - gpu->count = info.count; - return gpu; -} - -int gpu_release(void*, request_gpu_t* gpu) -{ - sp<IMemory> regs; - - { // scope for lock - Mutex::Autolock _l(gRegionsLock); - regs = static_cast<IMemory*>(gpu->regs.user); - gpu->regs.user = 0; - if (regs != 0) regs->decStrong(gpu); - - for (int i=0 ; i<gpu->count ; i++) { - sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user)); - gpu->gpu[i].user = 0; - if (r != 0) r->decStrong(gpu); - } - } - - // there is a special transaction to relinquish the GPU - // (it will happen automatically anyway if we don't do this) - Parcel data, reply; - // NOTE: this transaction does not require an interface token - regs->asBinder()->transact(1000, data, &reply); - return 1; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/opengl/libs/EGL/hooks.cpp b/opengl/libs/EGL/hooks.cpp new file mode 100644 index 0000000..2246366 --- /dev/null +++ b/opengl/libs/EGL/hooks.cpp @@ -0,0 +1,67 @@ +/* + ** Copyright 2009, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <cutils/log.h> + +#include "hooks.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +void gl_unimplemented() { + LOGE("called unimplemented OpenGL ES API"); +} + + +// ---------------------------------------------------------------------------- +// GL / EGL hooks +// ---------------------------------------------------------------------------- + +#undef GL_ENTRY +#undef EGL_ENTRY +#define GL_ENTRY(_r, _api, ...) #_api, +#define EGL_ENTRY(_r, _api, ...) #_api, + +char const * const gl_names[] = { + #include "GLES_CM/gl_entries.in" + #include "GLES_CM/glext_entries.in" + NULL +}; + +char const * const gl2_names[] = { + #include "GLES2/gl2_entries.in" + #include "GLES2/gl2ext_entries.in" + NULL +}; + +char const * const egl_names[] = { + #include "egl_entries.in" + NULL +}; + +#undef GL_ENTRY +#undef EGL_ENTRY + + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp new file mode 100644 index 0000000..e5358c3 --- /dev/null +++ b/opengl/libs/GLES2/gl2.cpp @@ -0,0 +1,111 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include <sys/ioctl.h> + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include "hooks.h" +#include "egl_impl.h" + +using namespace android; + +// ---------------------------------------------------------------------------- +// Actual GL entry-points +// ---------------------------------------------------------------------------- + +#undef API_ENTRY +#undef CALL_GL_API +#undef CALL_GL_API_RETURN + +#if USE_FAST_TLS_KEY + + #define API_ENTRY(_api) __attribute__((naked)) _api + + #define CALL_GL_API(_api, ...) \ + asm volatile( \ + "mov r12, #0xFFFF0FFF \n" \ + "ldr r12, [r12, #-15] \n" \ + "ldr r12, [r12, %[tls]] \n" \ + "cmp r12, #0 \n" \ + "ldrne pc, [r12, %[api]] \n" \ + "bx lr \n" \ + : \ + : [tls] "J"(TLS_SLOT_OPENGL_API*4), \ + [api] "J"(__builtin_offsetof(gl_hooks_t, gl2._api)) \ + : \ + ); + + #define CALL_GL_API_RETURN(_api, ...) \ + CALL_GL_API(_api, __VA_ARGS__) \ + return 0; // placate gcc's warnings. never reached. + +#else + + #define API_ENTRY(_api) _api + + #define CALL_GL_API(_api, ...) \ + gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \ + _c->_api(__VA_ARGS__) + + #define CALL_GL_API_RETURN(_api, ...) \ + gl_hooks_t::gl2_t const * const _c = &getGlThreadSpecific()->gl2; \ + return _c->_api(__VA_ARGS__) + +#endif + + +extern "C" { +#include "gl2_api.in" +#include "gl2ext_api.in" +} + +#undef API_ENTRY +#undef CALL_GL_API +#undef CALL_GL_API_RETURN + + +/* + * These GL calls are special because they need to EGL to retrieve some + * informations before they can execute. + */ + +extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); +extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); + + +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) +{ + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetTexture2DOES(target, implImage); +} + +void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) +{ + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetRenderbufferStorageOES(target, image); +} + diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in new file mode 100644 index 0000000..9c2e69a --- /dev/null +++ b/opengl/libs/GLES2/gl2_api.in @@ -0,0 +1,426 @@ +void API_ENTRY(glActiveTexture)(GLenum texture) { + CALL_GL_API(glActiveTexture, texture); +} +void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) { + CALL_GL_API(glAttachShader, program, shader); +} +void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const char* name) { + CALL_GL_API(glBindAttribLocation, program, index, name); +} +void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) { + CALL_GL_API(glBindBuffer, target, buffer); +} +void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer) { + CALL_GL_API(glBindFramebuffer, target, framebuffer); +} +void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer) { + CALL_GL_API(glBindRenderbuffer, target, renderbuffer); +} +void API_ENTRY(glBindTexture)(GLenum target, GLuint texture) { + CALL_GL_API(glBindTexture, target, texture); +} +void API_ENTRY(glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + CALL_GL_API(glBlendColor, red, green, blue, alpha); +} +void API_ENTRY(glBlendEquation)( GLenum mode ) { + CALL_GL_API(glBlendEquation, mode); +} +void API_ENTRY(glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) { + CALL_GL_API(glBlendEquationSeparate, modeRGB, modeAlpha); +} +void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) { + CALL_GL_API(glBlendFunc, sfactor, dfactor); +} +void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { + CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha); +} +void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void* data, GLenum usage) { + CALL_GL_API(glBufferData, target, size, data, usage); +} +void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { + CALL_GL_API(glBufferSubData, target, offset, size, data); +} +GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) { + CALL_GL_API_RETURN(glCheckFramebufferStatus, target); +} +void API_ENTRY(glClear)(GLbitfield mask) { + CALL_GL_API(glClear, mask); +} +void API_ENTRY(glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + CALL_GL_API(glClearColor, red, green, blue, alpha); +} +void API_ENTRY(glClearDepthf)(GLclampf depth) { + CALL_GL_API(glClearDepthf, depth); +} +void API_ENTRY(glClearStencil)(GLint s) { + CALL_GL_API(glClearStencil, s); +} +void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { + CALL_GL_API(glColorMask, red, green, blue, alpha); +} +void API_ENTRY(glCompileShader)(GLuint shader) { + CALL_GL_API(glCompileShader, shader); +} +void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) { + CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data); +} +void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) { + CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data); +} +void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { + CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y, width, height, border); +} +void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glCopyTexSubImage2D, target, level, xoffset, yoffset, x, y, width, height); +} +GLuint API_ENTRY(glCreateProgram)(void) { + CALL_GL_API_RETURN(glCreateProgram); +} +GLuint API_ENTRY(glCreateShader)(GLenum type) { + CALL_GL_API_RETURN(glCreateShader, type); +} +void API_ENTRY(glCullFace)(GLenum mode) { + CALL_GL_API(glCullFace, mode); +} +void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint* buffers) { + CALL_GL_API(glDeleteBuffers, n, buffers); +} +void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) { + CALL_GL_API(glDeleteFramebuffers, n, framebuffers); +} +void API_ENTRY(glDeleteProgram)(GLuint program) { + CALL_GL_API(glDeleteProgram, program); +} +void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) { + CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers); +} +void API_ENTRY(glDeleteShader)(GLuint shader) { + CALL_GL_API(glDeleteShader, shader); +} +void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint* textures) { + CALL_GL_API(glDeleteTextures, n, textures); +} +void API_ENTRY(glDepthFunc)(GLenum func) { + CALL_GL_API(glDepthFunc, func); +} +void API_ENTRY(glDepthMask)(GLboolean flag) { + CALL_GL_API(glDepthMask, flag); +} +void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar) { + CALL_GL_API(glDepthRangef, zNear, zFar); +} +void API_ENTRY(glDetachShader)(GLuint program, GLuint shader) { + CALL_GL_API(glDetachShader, program, shader); +} +void API_ENTRY(glDisable)(GLenum cap) { + CALL_GL_API(glDisable, cap); +} +void API_ENTRY(glDisableVertexAttribArray)(GLuint index) { + CALL_GL_API(glDisableVertexAttribArray, index); +} +void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) { + CALL_GL_API(glDrawArrays, mode, first, count); +} +void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void* indices) { + CALL_GL_API(glDrawElements, mode, count, type, indices); +} +void API_ENTRY(glEnable)(GLenum cap) { + CALL_GL_API(glEnable, cap); +} +void API_ENTRY(glEnableVertexAttribArray)(GLuint index) { + CALL_GL_API(glEnableVertexAttribArray, index); +} +void API_ENTRY(glFinish)(void) { + CALL_GL_API(glFinish); +} +void API_ENTRY(glFlush)(void) { + CALL_GL_API(glFlush); +} +void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { + CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer); +} +void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level); +} +void API_ENTRY(glFrontFace)(GLenum mode) { + CALL_GL_API(glFrontFace, mode); +} +void API_ENTRY(glGenBuffers)(GLsizei n, GLuint* buffers) { + CALL_GL_API(glGenBuffers, n, buffers); +} +void API_ENTRY(glGenerateMipmap)(GLenum target) { + CALL_GL_API(glGenerateMipmap, target); +} +void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers) { + CALL_GL_API(glGenFramebuffers, n, framebuffers); +} +void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) { + CALL_GL_API(glGenRenderbuffers, n, renderbuffers); +} +void API_ENTRY(glGenTextures)(GLsizei n, GLuint* textures) { + CALL_GL_API(glGenTextures, n, textures); +} +void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) { + CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name); +} +void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) { + CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name); +} +void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { + CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders); +} +int API_ENTRY(glGetAttribLocation)(GLuint program, const char* name) { + CALL_GL_API_RETURN(glGetAttribLocation, program, name); +} +void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params) { + CALL_GL_API(glGetBooleanv, pname, params); +} +void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) { + CALL_GL_API(glGetBufferParameteriv, target, pname, params); +} +GLenum API_ENTRY(glGetError)(void) { + CALL_GL_API_RETURN(glGetError); +} +void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params) { + CALL_GL_API(glGetFloatv, pname, params); +} +void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) { + CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params); +} +void API_ENTRY(glGetIntegerv)(GLenum pname, GLint* params) { + CALL_GL_API(glGetIntegerv, pname, params); +} +void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint* params) { + CALL_GL_API(glGetProgramiv, program, pname, params); +} +void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) { + CALL_GL_API(glGetProgramInfoLog, program, bufsize, length, infolog); +} +void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) { + CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params); +} +void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) { + CALL_GL_API(glGetShaderiv, shader, pname, params); +} +void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) { + CALL_GL_API(glGetShaderInfoLog, shader, bufsize, length, infolog); +} +void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { + CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision); +} +void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) { + CALL_GL_API(glGetShaderSource, shader, bufsize, length, source); +} +const GLubyte* API_ENTRY(glGetString)(GLenum name) { + CALL_GL_API_RETURN(glGetString, name); +} +void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) { + CALL_GL_API(glGetTexParameterfv, target, pname, params); +} +void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) { + CALL_GL_API(glGetTexParameteriv, target, pname, params); +} +void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params) { + CALL_GL_API(glGetUniformfv, program, location, params); +} +void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params) { + CALL_GL_API(glGetUniformiv, program, location, params); +} +int API_ENTRY(glGetUniformLocation)(GLuint program, const char* name) { + CALL_GL_API_RETURN(glGetUniformLocation, program, name); +} +void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) { + CALL_GL_API(glGetVertexAttribfv, index, pname, params); +} +void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) { + CALL_GL_API(glGetVertexAttribiv, index, pname, params); +} +void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer) { + CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer); +} +void API_ENTRY(glHint)(GLenum target, GLenum mode) { + CALL_GL_API(glHint, target, mode); +} +GLboolean API_ENTRY(glIsBuffer)(GLuint buffer) { + CALL_GL_API_RETURN(glIsBuffer, buffer); +} +GLboolean API_ENTRY(glIsEnabled)(GLenum cap) { + CALL_GL_API_RETURN(glIsEnabled, cap); +} +GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer) { + CALL_GL_API_RETURN(glIsFramebuffer, framebuffer); +} +GLboolean API_ENTRY(glIsProgram)(GLuint program) { + CALL_GL_API_RETURN(glIsProgram, program); +} +GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer) { + CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer); +} +GLboolean API_ENTRY(glIsShader)(GLuint shader) { + CALL_GL_API_RETURN(glIsShader, shader); +} +GLboolean API_ENTRY(glIsTexture)(GLuint texture) { + CALL_GL_API_RETURN(glIsTexture, texture); +} +void API_ENTRY(glLineWidth)(GLfloat width) { + CALL_GL_API(glLineWidth, width); +} +void API_ENTRY(glLinkProgram)(GLuint program) { + CALL_GL_API(glLinkProgram, program); +} +void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) { + CALL_GL_API(glPixelStorei, pname, param); +} +void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) { + CALL_GL_API(glPolygonOffset, factor, units); +} +void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { + CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels); +} +void API_ENTRY(glReleaseShaderCompiler)(void) { + CALL_GL_API(glReleaseShaderCompiler); +} +void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { + CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height); +} +void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) { + CALL_GL_API(glSampleCoverage, value, invert); +} +void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glScissor, x, y, width, height); +} +void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) { + CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length); +} +void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length) { + CALL_GL_API(glShaderSource, shader, count, string, length); +} +void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) { + CALL_GL_API(glStencilFunc, func, ref, mask); +} +void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) { + CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask); +} +void API_ENTRY(glStencilMask)(GLuint mask) { + CALL_GL_API(glStencilMask, mask); +} +void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask) { + CALL_GL_API(glStencilMaskSeparate, face, mask); +} +void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) { + CALL_GL_API(glStencilOp, fail, zfail, zpass); +} +void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { + CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass); +} +void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { + CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels); +} +void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) { + CALL_GL_API(glTexParameterf, target, pname, param); +} +void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) { + CALL_GL_API(glTexParameterfv, target, pname, params); +} +void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) { + CALL_GL_API(glTexParameteri, target, pname, param); +} +void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) { + CALL_GL_API(glTexParameteriv, target, pname, params); +} +void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) { + CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels); +} +void API_ENTRY(glUniform1f)(GLint location, GLfloat x) { + CALL_GL_API(glUniform1f, location, x); +} +void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) { + CALL_GL_API(glUniform1fv, location, count, v); +} +void API_ENTRY(glUniform1i)(GLint location, GLint x) { + CALL_GL_API(glUniform1i, location, x); +} +void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint* v) { + CALL_GL_API(glUniform1iv, location, count, v); +} +void API_ENTRY(glUniform2f)(GLint location, GLfloat x, GLfloat y) { + CALL_GL_API(glUniform2f, location, x, y); +} +void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) { + CALL_GL_API(glUniform2fv, location, count, v); +} +void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y) { + CALL_GL_API(glUniform2i, location, x, y); +} +void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint* v) { + CALL_GL_API(glUniform2iv, location, count, v); +} +void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glUniform3f, location, x, y, z); +} +void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) { + CALL_GL_API(glUniform3fv, location, count, v); +} +void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z) { + CALL_GL_API(glUniform3i, location, x, y, z); +} +void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint* v) { + CALL_GL_API(glUniform3iv, location, count, v); +} +void API_ENTRY(glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { + CALL_GL_API(glUniform4f, location, x, y, z, w); +} +void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) { + CALL_GL_API(glUniform4fv, location, count, v); +} +void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) { + CALL_GL_API(glUniform4i, location, x, y, z, w); +} +void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint* v) { + CALL_GL_API(glUniform4iv, location, count, v); +} +void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value); +} +void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value); +} +void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value); +} +void API_ENTRY(glUseProgram)(GLuint program) { + CALL_GL_API(glUseProgram, program); +} +void API_ENTRY(glValidateProgram)(GLuint program) { + CALL_GL_API(glValidateProgram, program); +} +void API_ENTRY(glVertexAttrib1f)(GLuint indx, GLfloat x) { + CALL_GL_API(glVertexAttrib1f, indx, x); +} +void API_ENTRY(glVertexAttrib1fv)(GLuint indx, const GLfloat* values) { + CALL_GL_API(glVertexAttrib1fv, indx, values); +} +void API_ENTRY(glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) { + CALL_GL_API(glVertexAttrib2f, indx, x, y); +} +void API_ENTRY(glVertexAttrib2fv)(GLuint indx, const GLfloat* values) { + CALL_GL_API(glVertexAttrib2fv, indx, values); +} +void API_ENTRY(glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) { + CALL_GL_API(glVertexAttrib3f, indx, x, y, z); +} +void API_ENTRY(glVertexAttrib3fv)(GLuint indx, const GLfloat* values) { + CALL_GL_API(glVertexAttrib3fv, indx, values); +} +void API_ENTRY(glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { + CALL_GL_API(glVertexAttrib4f, indx, x, y, z, w); +} +void API_ENTRY(glVertexAttrib4fv)(GLuint indx, const GLfloat* values) { + CALL_GL_API(glVertexAttrib4fv, indx, values); +} +void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) { + CALL_GL_API(glVertexAttribPointer, indx, size, type, normalized, stride, ptr); +} +void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glViewport, x, y, width, height); +} diff --git a/opengl/libs/GLES2/gl2_entries.in b/opengl/libs/GLES2/gl2_entries.in new file mode 100644 index 0000000..6a41b94 --- /dev/null +++ b/opengl/libs/GLES2/gl2_entries.in @@ -0,0 +1,142 @@ +GL_ENTRY(void, glActiveTexture, GLenum texture) +GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader) +GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name) +GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer) +GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer) +GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer) +GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture) +GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +GL_ENTRY(void, glBlendEquation, GLenum mode ) +GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha) +GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor) +GL_ENTRY(void, glBlendFuncSeparate, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void* data, GLenum usage) +GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void* data) +GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target) +GL_ENTRY(void, glClear, GLbitfield mask) +GL_ENTRY(void, glClearColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +GL_ENTRY(void, glClearDepthf, GLclampf depth) +GL_ENTRY(void, glClearStencil, GLint s) +GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +GL_ENTRY(void, glCompileShader, GLuint shader) +GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) +GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) +GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(GLuint, glCreateProgram, void) +GL_ENTRY(GLuint, glCreateShader, GLenum type) +GL_ENTRY(void, glCullFace, GLenum mode) +GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint* buffers) +GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint* framebuffers) +GL_ENTRY(void, glDeleteProgram, GLuint program) +GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers) +GL_ENTRY(void, glDeleteShader, GLuint shader) +GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint* textures) +GL_ENTRY(void, glDepthFunc, GLenum func) +GL_ENTRY(void, glDepthMask, GLboolean flag) +GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar) +GL_ENTRY(void, glDetachShader, GLuint program, GLuint shader) +GL_ENTRY(void, glDisable, GLenum cap) +GL_ENTRY(void, glDisableVertexAttribArray, GLuint index) +GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count) +GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void* indices) +GL_ENTRY(void, glEnable, GLenum cap) +GL_ENTRY(void, glEnableVertexAttribArray, GLuint index) +GL_ENTRY(void, glFinish, void) +GL_ENTRY(void, glFlush, void) +GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +GL_ENTRY(void, glFrontFace, GLenum mode) +GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint* buffers) +GL_ENTRY(void, glGenerateMipmap, GLenum target) +GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint* framebuffers) +GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers) +GL_ENTRY(void, glGenTextures, GLsizei n, GLuint* textures) +GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) +GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name) +GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean* params) +GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint* params) +GL_ENTRY(GLenum, glGetError, void) +GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat* params) +GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint* params) +GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint* params) +GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params) +GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) +GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params) +GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params) +GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) +GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source) +GL_ENTRY(const GLubyte*, glGetString, GLenum name) +GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat* params) +GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint* params) +GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params) +GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params) +GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name) +GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params) +GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params) +GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer) +GL_ENTRY(void, glHint, GLenum target, GLenum mode) +GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer) +GL_ENTRY(GLboolean, glIsEnabled, GLenum cap) +GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer) +GL_ENTRY(GLboolean, glIsProgram, GLuint program) +GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer) +GL_ENTRY(GLboolean, glIsShader, GLuint shader) +GL_ENTRY(GLboolean, glIsTexture, GLuint texture) +GL_ENTRY(void, glLineWidth, GLfloat width) +GL_ENTRY(void, glLinkProgram, GLuint program) +GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param) +GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units) +GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) +GL_ENTRY(void, glReleaseShaderCompiler, void) +GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +GL_ENTRY(void, glSampleCoverage, GLclampf value, GLboolean invert) +GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) +GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length) +GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask) +GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask) +GL_ENTRY(void, glStencilMask, GLuint mask) +GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask) +GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass) +GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param) +GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat* params) +GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param) +GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint* params) +GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) +GL_ENTRY(void, glUniform1f, GLint location, GLfloat x) +GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat* v) +GL_ENTRY(void, glUniform1i, GLint location, GLint x) +GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint* v) +GL_ENTRY(void, glUniform2f, GLint location, GLfloat x, GLfloat y) +GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat* v) +GL_ENTRY(void, glUniform2i, GLint location, GLint x, GLint y) +GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint* v) +GL_ENTRY(void, glUniform3f, GLint location, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat* v) +GL_ENTRY(void, glUniform3i, GLint location, GLint x, GLint y, GLint z) +GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint* v) +GL_ENTRY(void, glUniform4f, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat* v) +GL_ENTRY(void, glUniform4i, GLint location, GLint x, GLint y, GLint z, GLint w) +GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint* v) +GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +GL_ENTRY(void, glUseProgram, GLuint program) +GL_ENTRY(void, glValidateProgram, GLuint program) +GL_ENTRY(void, glVertexAttrib1f, GLuint indx, GLfloat x) +GL_ENTRY(void, glVertexAttrib1fv, GLuint indx, const GLfloat* values) +GL_ENTRY(void, glVertexAttrib2f, GLuint indx, GLfloat x, GLfloat y) +GL_ENTRY(void, glVertexAttrib2fv, GLuint indx, const GLfloat* values) +GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z) +GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values) +GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values) +GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) +GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height) diff --git a/opengl/libs/GLES2/gl2ext_api.in b/opengl/libs/GLES2/gl2ext_api.in new file mode 100644 index 0000000..6eeecb3 --- /dev/null +++ b/opengl/libs/GLES2/gl2ext_api.in @@ -0,0 +1,105 @@ +void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) { + CALL_GL_API(glEGLImageTargetTexture2DOES, target, image); +} +void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) { + CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image); +} +void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) { + CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary); +} +void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { + CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length); +} +void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) { + CALL_GL_API_RETURN(glMapBufferOES, target, access); +} +GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) { + CALL_GL_API_RETURN(glUnmapBufferOES, target); +} +void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) { + CALL_GL_API(glGetBufferPointervOES, target, pname, params); +} +void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) { + CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels); +} +void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { + CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); +} +void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) { + CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height); +} +void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data) { + CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data); +} +void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) { + CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); +} +void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) { + CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset); +} +void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint *numGroups, GLsizei groupsSize, GLuint *groups) { + CALL_GL_API(glGetPerfMonitorGroupsAMD, numGroups, groupsSize, groups); +} +void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) { + CALL_GL_API(glGetPerfMonitorCountersAMD, group, numCounters, maxActiveCounters, counterSize, counters); +} +void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, char *groupString) { + CALL_GL_API(glGetPerfMonitorGroupStringAMD, group, bufSize, length, groupString); +} +void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString) { + CALL_GL_API(glGetPerfMonitorCounterStringAMD, group, counter, bufSize, length, counterString); +} +void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void *data) { + CALL_GL_API(glGetPerfMonitorCounterInfoAMD, group, counter, pname, data); +} +void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint *monitors) { + CALL_GL_API(glGenPerfMonitorsAMD, n, monitors); +} +void API_ENTRY(glDeletePerfMonitorsAMD)(GLsizei n, GLuint *monitors) { + CALL_GL_API(glDeletePerfMonitorsAMD, n, monitors); +} +void API_ENTRY(glSelectPerfMonitorCountersAMD)(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList) { + CALL_GL_API(glSelectPerfMonitorCountersAMD, monitor, enable, group, numCounters, countersList); +} +void API_ENTRY(glBeginPerfMonitorAMD)(GLuint monitor) { + CALL_GL_API(glBeginPerfMonitorAMD, monitor); +} +void API_ENTRY(glEndPerfMonitorAMD)(GLuint monitor) { + CALL_GL_API(glEndPerfMonitorAMD, monitor); +} +void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) { + CALL_GL_API(glGetPerfMonitorCounterDataAMD, monitor, pname, dataSize, data, bytesWritten); +} +void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) { + CALL_GL_API(glDeleteFencesNV, n, fences); +} +void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) { + CALL_GL_API(glGenFencesNV, n, fences); +} +GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) { + CALL_GL_API_RETURN(glIsFenceNV, fence); +} +GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) { + CALL_GL_API_RETURN(glTestFenceNV, fence); +} +void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) { + CALL_GL_API(glGetFenceivNV, fence, pname, params); +} +void API_ENTRY(glFinishFenceNV)(GLuint fence) { + CALL_GL_API(glFinishFenceNV, fence); +} +void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) { + CALL_GL_API(glSetFenceNV, fence, condition); +} +void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) { + CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls); +} +void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString) { + CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString); +} +void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) { + CALL_GL_API(glEnableDriverControlQCOM, driverControl); +} +void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) { + CALL_GL_API(glDisableDriverControlQCOM, driverControl); +} diff --git a/opengl/libs/GLES2/gl2ext_entries.in b/opengl/libs/GLES2/gl2ext_entries.in new file mode 100644 index 0000000..e608f5d --- /dev/null +++ b/opengl/libs/GLES2/gl2ext_entries.in @@ -0,0 +1,35 @@ +GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image) +GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) +GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length) +GL_ENTRY(void*, glMapBufferOES, GLenum target, GLenum access) +GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target) +GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params) +GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) +GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) +GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data) +GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) +GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) +GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups) +GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) +GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString) +GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString) +GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data) +GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors) +GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors) +GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList) +GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor) +GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor) +GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) +GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences) +GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences) +GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence) +GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence) +GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params) +GL_ENTRY(void, glFinishFenceNV, GLuint fence) +GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition) +GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls) +GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString) +GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl) +GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl) diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp index 384b59a..3204d9a 100644 --- a/opengl/libs/GLES_CM/gl.cpp +++ b/opengl/libs/GLES_CM/gl.cpp @@ -14,8 +14,6 @@ ** limitations under the License. */ -#define LOG_TAG "GLES_CM" - #include <ctype.h> #include <string.h> #include <errno.h> @@ -121,16 +119,25 @@ extern "C" { /* - * These GL calls are special because they need to call into EGL to retrieve - * some informations before they can execute. + * These GL calls are special because they need to EGL to retrieve some + * informations before they can execute. */ +extern "C" void __glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); +extern "C" void __glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image); + void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) { + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetTexture2DOES(target, implImage); } void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) { + GLeglImageOES implImage = + (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); + __glEGLImageTargetRenderbufferStorageOES(target, image); } diff --git a/opengl/libs/gl_entries.in b/opengl/libs/GLES_CM/gl_entries.in index d7cc5da..d7cc5da 100644 --- a/opengl/libs/gl_entries.in +++ b/opengl/libs/GLES_CM/gl_entries.in diff --git a/opengl/libs/glext_entries.in b/opengl/libs/GLES_CM/glext_entries.in index dd09c71..dd09c71 100644 --- a/opengl/libs/glext_entries.in +++ b/opengl/libs/GLES_CM/glext_entries.in diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h index 312b176..c5f753d 100644 --- a/opengl/libs/egl_impl.h +++ b/opengl/libs/egl_impl.h @@ -31,13 +31,15 @@ struct gl_hooks_t; struct egl_connection_t { - void volatile * dso; + void * dso; gl_hooks_t * hooks; EGLint major; EGLint minor; int unavailable; }; +EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image); + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/opengl/libs/gl_enums.in b/opengl/libs/gl_enums.in deleted file mode 100644 index ffc2fad..0000000 --- a/opengl/libs/gl_enums.in +++ /dev/null @@ -1,261 +0,0 @@ -GLENUM(GL_POINTS, 0x0000) -GLENUM(GL_LINES, 0x0001) -GLENUM(GL_LINE_LOOP, 0x0002) -GLENUM(GL_LINE_STRIP, 0x0003) -GLENUM(GL_TRIANGLES, 0x0004) -GLENUM(GL_TRIANGLE_STRIP, 0x0005) -GLENUM(GL_TRIANGLE_FAN, 0x0006) -GLENUM(GL_ADD, 0x0104) -GLENUM(GL_NEVER, 0x0200) -GLENUM(GL_LESS, 0x0201) -GLENUM(GL_EQUAL, 0x0202) -GLENUM(GL_LEQUAL, 0x0203) -GLENUM(GL_GREATER, 0x0204) -GLENUM(GL_NOTEQUAL, 0x0205) -GLENUM(GL_GEQUAL, 0x0206) -GLENUM(GL_ALWAYS, 0x0207) -GLENUM(GL_SRC_COLOR, 0x0300) -GLENUM(GL_ONE_MINUS_SRC_COLOR, 0x0301) -GLENUM(GL_SRC_ALPHA, 0x0302) -GLENUM(GL_ONE_MINUS_SRC_ALPHA, 0x0303) -GLENUM(GL_DST_ALPHA, 0x0304) -GLENUM(GL_ONE_MINUS_DST_ALPHA, 0x0305) -GLENUM(GL_DST_COLOR, 0x0306) -GLENUM(GL_ONE_MINUS_DST_COLOR, 0x0307) -GLENUM(GL_SRC_ALPHA_SATURATE, 0x0308) -GLENUM(GL_FRONT, 0x0404) -GLENUM(GL_BACK, 0x0405) -GLENUM(GL_FRONT_AND_BACK, 0x0408) -GLENUM(GL_INVALID_ENUM, 0x0500) -GLENUM(GL_INVALID_VALUE, 0x0501) -GLENUM(GL_INVALID_OPERATION, 0x0502) -GLENUM(GL_STACK_OVERFLOW, 0x0503) -GLENUM(GL_STACK_UNDERFLOW, 0x0504) -GLENUM(GL_OUT_OF_MEMORY, 0x0505) -GLENUM(GL_EXP, 0x0800) -GLENUM(GL_EXP2, 0x0801) -GLENUM(GL_CW, 0x0900) -GLENUM(GL_CCW, 0x0901) -GLENUM(GL_POINT_SMOOTH, 0x0B10) -GLENUM(GL_SMOOTH_POINT_SIZE_RANGE, 0x0B12) -GLENUM(GL_LINE_SMOOTH, 0x0B20) -GLENUM(GL_SMOOTH_LINE_WIDTH_RANGE, 0x0B22) -GLENUM(GL_CULL_FACE, 0x0B44) -GLENUM(GL_LIGHTING, 0x0B50) -GLENUM(GL_LIGHT_MODEL_TWO_SIDE, 0x0B52) -GLENUM(GL_LIGHT_MODEL_AMBIENT, 0x0B53) -GLENUM(GL_COLOR_MATERIAL, 0x0B57) -GLENUM(GL_FOG, 0x0B60) -GLENUM(GL_FOG_DENSITY, 0x0B62) -GLENUM(GL_FOG_START, 0x0B63) -GLENUM(GL_FOG_END, 0x0B64) -GLENUM(GL_FOG_MODE, 0x0B65) -GLENUM(GL_FOG_COLOR, 0x0B66) -GLENUM(GL_DEPTH_TEST, 0x0B71) -GLENUM(GL_STENCIL_TEST, 0x0B90) -GLENUM(GL_NORMALIZE, 0x0BA1) -GLENUM(GL_ALPHA_TEST, 0x0BC0) -GLENUM(GL_DITHER, 0x0BD0) -GLENUM(GL_BLEND, 0x0BE2) -GLENUM(GL_COLOR_LOGIC_OP, 0x0BF2) -GLENUM(GL_SCISSOR_TEST, 0x0C11) -GLENUM(GL_PERSPECTIVE_CORRECTION_HINT, 0x0C50) -GLENUM(GL_POINT_SMOOTH_HINT, 0x0C51) -GLENUM(GL_LINE_SMOOTH_HINT, 0x0C52) -GLENUM(GL_POLYGON_SMOOTH_HINT, 0x0C53) -GLENUM(GL_FOG_HINT, 0x0C54) -GLENUM(GL_UNPACK_ALIGNMENT, 0x0CF5) -GLENUM(GL_PACK_ALIGNMENT, 0x0D05) -GLENUM(GL_MAX_LIGHTS, 0x0D31) -GLENUM(GL_MAX_CLIP_PLANES, 0x0D32) -GLENUM(GL_MAX_TEXTURE_SIZE, 0x0D33) -GLENUM(GL_MAX_MODELVIEW_STACK_DEPTH, 0x0D36) -GLENUM(GL_MAX_PROJECTION_STACK_DEPTH, 0x0D38) -GLENUM(GL_MAX_TEXTURE_STACK_DEPTH, 0x0D39) -GLENUM(GL_MAX_VIEWPORT_DIMS, 0x0D3A) -GLENUM(GL_RED_BITS, 0x0D52) -GLENUM(GL_GREEN_BITS, 0x0D53) -GLENUM(GL_BLUE_BITS, 0x0D54) -GLENUM(GL_ALPHA_BITS, 0x0D55) -GLENUM(GL_DEPTH_BITS, 0x0D56) -GLENUM(GL_STENCIL_BITS, 0x0D57) -GLENUM(GL_TEXTURE_2D, 0x0DE1) -GLENUM(GL_DONT_CARE, 0x1100) -GLENUM(GL_FASTEST, 0x1101) -GLENUM(GL_NICEST, 0x1102) -GLENUM(GL_AMBIENT, 0x1200) -GLENUM(GL_DIFFUSE, 0x1201) -GLENUM(GL_SPECULAR, 0x1202) -GLENUM(GL_POSITION, 0x1203) -GLENUM(GL_SPOT_DIRECTION, 0x1204) -GLENUM(GL_SPOT_EXPONENT, 0x1205) -GLENUM(GL_SPOT_CUTOFF, 0x1206) -GLENUM(GL_CONSTANT_ATTENUATION, 0x1207) -GLENUM(GL_LINEAR_ATTENUATION, 0x1208) -GLENUM(GL_QUADRATIC_ATTENUATION, 0x1209) -GLENUM(GL_BYTE, 0x1400) -GLENUM(GL_UNSIGNED_BYTE, 0x1401) -GLENUM(GL_SHORT, 0x1402) -GLENUM(GL_UNSIGNED_SHORT, 0x1403) -GLENUM(GL_FLOAT, 0x1406) -GLENUM(GL_FIXED, 0x140C) -GLENUM(GL_CLEAR, 0x1500) -GLENUM(GL_AND, 0x1501) -GLENUM(GL_AND_REVERSE, 0x1502) -GLENUM(GL_COPY, 0x1503) -GLENUM(GL_AND_INVERTED, 0x1504) -GLENUM(GL_NOOP, 0x1505) -GLENUM(GL_XOR, 0x1506) -GLENUM(GL_OR, 0x1507) -GLENUM(GL_NOR, 0x1508) -GLENUM(GL_EQUIV, 0x1509) -GLENUM(GL_INVERT, 0x150A) -GLENUM(GL_OR_REVERSE, 0x150B) -GLENUM(GL_COPY_INVERTED, 0x150C) -GLENUM(GL_OR_INVERTED, 0x150D) -GLENUM(GL_NAND, 0x150E) -GLENUM(GL_SET, 0x150F) -GLENUM(GL_EMISSION, 0x1600) -GLENUM(GL_SHININESS, 0x1601) -GLENUM(GL_AMBIENT_AND_DIFFUSE, 0x1602) -GLENUM(GL_MODELVIEW, 0x1700) -GLENUM(GL_PROJECTION, 0x1701) -GLENUM(GL_TEXTURE, 0x1702) -GLENUM(GL_ALPHA, 0x1906) -GLENUM(GL_RGB, 0x1907) -GLENUM(GL_RGBA, 0x1908) -GLENUM(GL_LUMINANCE, 0x1909) -GLENUM(GL_LUMINANCE_ALPHA, 0x190A) -GLENUM(GL_FLAT, 0x1D00) -GLENUM(GL_SMOOTH, 0x1D01) -GLENUM(GL_KEEP, 0x1E00) -GLENUM(GL_REPLACE, 0x1E01) -GLENUM(GL_REPLACE, 0x1E01) -GLENUM(GL_INCR, 0x1E02) -GLENUM(GL_DECR, 0x1E03) -GLENUM(GL_VENDOR, 0x1F00) -GLENUM(GL_RENDERER, 0x1F01) -GLENUM(GL_VERSION, 0x1F02) -GLENUM(GL_EXTENSIONS, 0x1F03) -GLENUM(GL_MODULATE, 0x2100) -GLENUM(GL_DECAL, 0x2101) -GLENUM(GL_TEXTURE_ENV_MODE, 0x2200) -GLENUM(GL_TEXTURE_ENV_COLOR, 0x2201) -GLENUM(GL_TEXTURE_ENV, 0x2300) -GLENUM(GL_NEAREST, 0x2600) -GLENUM(GL_LINEAR, 0x2601) -GLENUM(GL_NEAREST_MIPMAP_NEAREST, 0x2700) -GLENUM(GL_LINEAR_MIPMAP_NEAREST, 0x2701) -GLENUM(GL_NEAREST_MIPMAP_LINEAR, 0x2702) -GLENUM(GL_LINEAR_MIPMAP_LINEAR, 0x2703) -GLENUM(GL_TEXTURE_MAG_FILTER, 0x2800) -GLENUM(GL_TEXTURE_MIN_FILTER, 0x2801) -GLENUM(GL_TEXTURE_WRAP_S, 0x2802) -GLENUM(GL_TEXTURE_WRAP_T, 0x2803) -GLENUM(GL_CLAMP, 0x2900) -GLENUM(GL_REPEAT, 0x2901) -GLENUM(GL_CLIP_PLANE0, 0x3000) -GLENUM(GL_CLIP_PLANE1, 0x3001) -GLENUM(GL_CLIP_PLANE2, 0x3002) -GLENUM(GL_CLIP_PLANE3, 0x3003) -GLENUM(GL_CLIP_PLANE4, 0x3004) -GLENUM(GL_CLIP_PLANE5, 0x3005) -GLENUM(GL_LIGHT0, 0x4000) -GLENUM(GL_LIGHT1, 0x4001) -GLENUM(GL_LIGHT2, 0x4002) -GLENUM(GL_LIGHT3, 0x4003) -GLENUM(GL_LIGHT4, 0x4004) -GLENUM(GL_LIGHT5, 0x4005) -GLENUM(GL_LIGHT6, 0x4006) -GLENUM(GL_LIGHT7, 0x4007) -GLENUM(GL_DIRECT_TEXTURE_2D_QUALCOMM, 0x7E80) -GLENUM(GL_UNSIGNED_SHORT_4_4_4_4, 0x8033) -GLENUM(GL_UNSIGNED_SHORT_5_5_5_1, 0x8034) -GLENUM(GL_POLYGON_OFFSET_FILL, 0x8037) -GLENUM(GL_RESCALE_NORMAL, 0x803A) -GLENUM(GL_VERTEX_ARRAY, 0x8074) -GLENUM(GL_NORMAL_ARRAY, 0x8075) -GLENUM(GL_COLOR_ARRAY, 0x8076) -GLENUM(GL_TEXTURE_COORD_ARRAY, 0x8078) -GLENUM(GL_MULTISAMPLE, 0x809D) -GLENUM(GL_SAMPLE_ALPHA_TO_COVERAGE, 0x809E) -GLENUM(GL_SAMPLE_ALPHA_TO_ONE, 0x809F) -GLENUM(GL_SAMPLE_COVERAGE, 0x80A0) -GLENUM(GL_MAX_ELEMENTS_VERTICES, 0x80E8) -GLENUM(GL_MAX_ELEMENTS_INDICES, 0x80E9) -GLENUM(GL_CLAMP_TO_EDGE, 0x812F) -GLENUM(GL_GENERATE_MIPMAP, 0x8191) -GLENUM(GL_GENERATE_MIPMAP_HINT, 0x8192) -GLENUM(GL_UNSIGNED_SHORT_5_6_5, 0x8363) -GLENUM(GL_ALIASED_POINT_SIZE_RANGE, 0x846D) -GLENUM(GL_ALIASED_LINE_WIDTH_RANGE, 0x846E) -GLENUM(GL_TEXTURE0, 0x84C0) -GLENUM(GL_TEXTURE1, 0x84C1) -GLENUM(GL_TEXTURE2, 0x84C2) -GLENUM(GL_TEXTURE3, 0x84C3) -GLENUM(GL_TEXTURE4, 0x84C4) -GLENUM(GL_TEXTURE5, 0x84C5) -GLENUM(GL_TEXTURE6, 0x84C6) -GLENUM(GL_TEXTURE7, 0x84C7) -GLENUM(GL_TEXTURE8, 0x84C8) -GLENUM(GL_TEXTURE9, 0x84C9) -GLENUM(GL_TEXTURE10, 0x84CA) -GLENUM(GL_TEXTURE11, 0x84CB) -GLENUM(GL_TEXTURE12, 0x84CC) -GLENUM(GL_TEXTURE13, 0x84CD) -GLENUM(GL_TEXTURE14, 0x84CE) -GLENUM(GL_TEXTURE15, 0x84CF) -GLENUM(GL_TEXTURE16, 0x84D0) -GLENUM(GL_TEXTURE17, 0x84D1) -GLENUM(GL_TEXTURE18, 0x84D2) -GLENUM(GL_TEXTURE19, 0x84D3) -GLENUM(GL_TEXTURE20, 0x84D4) -GLENUM(GL_TEXTURE21, 0x84D5) -GLENUM(GL_TEXTURE22, 0x84D6) -GLENUM(GL_TEXTURE23, 0x84D7) -GLENUM(GL_TEXTURE24, 0x84D8) -GLENUM(GL_TEXTURE25, 0x84D9) -GLENUM(GL_TEXTURE26, 0x84DA) -GLENUM(GL_TEXTURE27, 0x84DB) -GLENUM(GL_TEXTURE28, 0x84DC) -GLENUM(GL_TEXTURE29, 0x84DD) -GLENUM(GL_TEXTURE30, 0x84DE) -GLENUM(GL_TEXTURE31, 0x84DF) -GLENUM(GL_MAX_TEXTURE_UNITS, 0x84E2) -GLENUM(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 0x86A2) -GLENUM(GL_COMPRESSED_TEXTURE_FORMATS, 0x86A3) -GLENUM(GL_BUFFER_SIZE, 0x8764) -GLENUM(GL_BUFFER_USAGE, 0x8765) -GLENUM(GL_POINT_SPRITE_OES, 0x8861) -GLENUM(GL_COORD_REPLACE_OES, 0x8862) -GLENUM(GL_ARRAY_BUFFER, 0x8892) -GLENUM(GL_ELEMENT_ARRAY_BUFFER, 0x8893) -GLENUM(GL_ARRAY_BUFFER_BINDING, 0x8894) -GLENUM(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0x8895) -GLENUM(GL_VERTEX_ARRAY_BUFFER_BINDING, 0x8896) -GLENUM(GL_NORMAL_ARRAY_BUFFER_BINDING, 0x8897) -GLENUM(GL_COLOR_ARRAY_BUFFER_BINDING, 0x8898) -GLENUM(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, 0x889A) -GLENUM(GL_STATIC_DRAW, 0x88E4) -GLENUM(GL_DYNAMIC_DRAW, 0x88E8) -GLENUM(GL_POINT_SIZE_ARRAY_TYPE_OES, 0x898A) -GLENUM(GL_POINT_SIZE_ARRAY_STRIDE_OES, 0x898B) -GLENUM(GL_POINT_SIZE_ARRAY_POINTER_OES, 0x898C) -GLENUM(GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898D) -GLENUM(GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898E) -GLENUM(GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES, 0x898F) -GLENUM(GL_PALETTE4_RGB8_OES, 0x8B90) -GLENUM(GL_PALETTE4_RGBA8_OES, 0x8B91) -GLENUM(GL_PALETTE4_R5_G6_B5_OES, 0x8B92) -GLENUM(GL_PALETTE4_RGBA4_OES, 0x8B93) -GLENUM(GL_PALETTE4_RGB5_A1_OES, 0x8B94) -GLENUM(GL_PALETTE8_RGB8_OES, 0x8B95) -GLENUM(GL_PALETTE8_RGBA8_OES, 0x8B96) -GLENUM(GL_PALETTE8_R5_G6_B5_OES, 0x8B97) -GLENUM(GL_PALETTE8_RGBA4_OES, 0x8B98) -GLENUM(GL_PALETTE8_RGB5_A1_OES, 0x8B99) -GLENUM(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, 0x8B9A) -GLENUM(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, 0x8B9B) -GLENUM(GL_POINT_SIZE_ARRAY_OES, 0x8B9C) -GLENUM(GL_TEXTURE_CROP_RECT_OES, 0x8B9D) -GLENUM(GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES, 0x8B9F) diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h index fd97254..37292ee 100644 --- a/opengl/libs/hooks.h +++ b/opengl/libs/hooks.h @@ -21,10 +21,14 @@ #include <string.h> #include <errno.h> +#include <pthread.h> + #include <EGL/egl.h> #include <EGL/eglext.h> #include <GLES/gl.h> #include <GLES/glext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> #if !defined(__arm__) #define USE_SLOW_BINDING 1 @@ -76,11 +80,15 @@ enum { struct gl_hooks_t { struct gl_t { - #include "gl_entries.in" - #include "glext_entries.in" + #include "GLES_CM/gl_entries.in" + #include "GLES_CM/glext_entries.in" } gl; + struct gl2_t { + #include "GLES2/gl2_entries.in" + #include "GLES2/gl2ext_entries.in" + } gl2; struct egl_t { - #include "egl_entries.in" + #include "EGL/egl_entries.in" } egl; struct gl_ext_t { void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void); @@ -94,6 +102,13 @@ struct gl_hooks_t { extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS]; extern pthread_key_t gGLWrapperKey; +extern "C" void gl_unimplemented(); + +extern char const * const gl_names[]; +extern char const * const gl2_names[]; +extern char const * const egl_names[]; + +// ---------------------------------------------------------------------------- #if USE_FAST_TLS_KEY diff --git a/opengl/libs/tools/enumextract.sh b/opengl/libs/tools/enumextract.sh deleted file mode 100644 index 5707302..0000000 --- a/opengl/libs/tools/enumextract.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -awk ' -/^#define GL_/ { - names[count] = $2; - values[count] = $3; - sort[count] = $3 + 0; - count++; -} -END { - for (i = 1; i < count; i++) { - for (j = 0; j < i; j++) { - if (sort[i] < sort[j]) { - tn = names[i]; - tv = values[i]; - ts = sort[i]; - names[i] = names[j]; - values[i] = values[j]; - sort[i] = sort[j]; - names[j] = tn; - values[j] = tv; - sort[j] = ts; - } - } - } - - for (i = 0; i < count; i++) { - printf("GLENUM(%s, %s)\n", names[i], values[i]); - } -} -' < $1 - diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles index 107768b..4f8eda4 100755 --- a/opengl/libs/tools/genfiles +++ b/opengl/libs/tools/genfiles @@ -15,6 +15,13 @@ # limitations under the License. ./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in -./glentrygen ../../include/GLES/gl.h > ../gl_entries.in +./glentrygen ../../include/GLES/gl.h > ../GLES_CM/gl_entries.in + ./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in -./glentrygen ../../include/GLES/glext.h > ../glext_entries.in +./glentrygen ../../include/GLES/glext.h > ../GLES_CM/glext_entries.in + +./glapigen ../../include/GLES2/gl2.h > ../GLES2/gl2_api.in +./glentrygen ../../include/GLES2/gl2.h > ../GLES2/gl2_entries.in + +./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in +./glentrygen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_entries.in diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen index a2c3a7b..bd8dda3 100755 --- a/opengl/libs/tools/glapigen +++ b/opengl/libs/tools/glapigen @@ -16,16 +16,23 @@ use strict; +sub rtrim($) +{ + my $string = shift; + $string =~ s/\s+$//; + return $string; +} + while (my $line = <>) { next if $line =~ /^\//; next if $line =~ /^#/; next if $line =~ /^\s*$/; - if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { + if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { next; } - my $type = $1; - my $name = $2; - my $args = $3; + my $type = rtrim($2); + my $name = $3; + my $args = $4; #printf("%s", $line); diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen index 5e0f7b6..170f041 100755 --- a/opengl/libs/tools/glentrygen +++ b/opengl/libs/tools/glentrygen @@ -16,16 +16,23 @@ use strict; +sub rtrim($) +{ + my $string = shift; + $string =~ s/\s+$//; + return $string; +} + while (my $line = <>) { next if $line =~ /^\//; next if $line =~ /^#/; next if $line =~ /^\s*$/; - if ($line !~ /^GL_API\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { + if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) { next; } - my $type = $1; - my $name = $2; - my $args = $3; + my $type = rtrim($2); + my $name = $3; + my $args = $4; printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args); } diff --git a/opengl/tests/copybits/Android.mk b/opengl/tests/copybits/Android.mk new file mode 100644 index 0000000..2876a1e --- /dev/null +++ b/opengl/tests/copybits/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + copybits.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libEGL \ + libGLESv1_CM \ + libui + +LOCAL_MODULE:= test-opengl-copybits + +LOCAL_MODULE_TAGS := tests + +##include $(BUILD_EXECUTABLE) + diff --git a/opengl/tests/copybits/copybits.cpp b/opengl/tests/copybits/copybits.cpp new file mode 100644 index 0000000..404932a --- /dev/null +++ b/opengl/tests/copybits/copybits.cpp @@ -0,0 +1,752 @@ +// Test software OpenGL hardware accelleration using copybits. + +#define LOG_TAG "copybits_test" + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <ui/PixelFormat.h> + +#include <cutils/log.h> +#include <cutils/native_handle.h> + +#include <utils/Atomic.h> + +#include <private/ui/SharedState.h> + +#include <hardware/gralloc.h> +#include <hardware/hardware.h> + +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <GLES/gl.h> +#include <GLES/glext.h> + +extern "C" EGLNativeWindowType android_createDisplaySurface(void); + +using namespace android; + +EGLDisplay eglDisplay; +EGLSurface eglSurface; +EGLContext eglContext; +GLuint texture; + +hw_module_t const* gralloc_module; +alloc_device_t *sAllocDev; + +#define FIXED_ONE 0x10000 /* 1.0 in 16.16 fixed point. */ + +int init_gl_surface(); +void free_gl_surface(); +void init_scene(); + +int create_physical_texture(); +int readTimer(); + +// =========================================================================== +// Buffer and implementation of android_native_buffer_t +// =========================================================================== + +class NativeBuffer; + +class Buffer : public android_native_buffer_t, + public LightRefBase<Buffer> +{ +public: + + // creates w * h buffer + Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage); + + // return status + status_t initCheck() const; + + + uint32_t getWidth() const { return mWidth; } + uint32_t getHeight() const { return mHeight; } + uint32_t getStride() const { return mStride; } + uint32_t getUsage() const { return mUsage; } + PixelFormat getPixelFormat() const { return mFormat; } + buffer_handle_t getHandle() const { return mBufferHandle; } + + android_native_buffer_t* getNativeBuffer() const; + + void setPixel(int x, int y, int r, int g, int b, int a); + +private: + friend class LightRefBase<Buffer>; + Buffer(const Buffer& rhs); + ~Buffer(); + Buffer& operator = (const Buffer& rhs); + const Buffer& operator = (const Buffer& rhs) const; + + status_t initSize(uint32_t w, uint32_t h); + + static void incRef(android_native_base_t* buffer); + static void decRef(android_native_base_t* buffer); + static int getHandlePriv(android_native_buffer_t const * buffer, + buffer_handle_t* handle); + + buffer_handle_t mBufferHandle; + ssize_t mInitCheck; + + uint32_t mWidth; + uint32_t mHeight; + uint32_t mStride; + uint32_t mVStride; + PixelFormat mFormat; + void* mData; + uint32_t mUsage; +}; + +Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, int usage) + : mBufferHandle(0), mInitCheck(NO_INIT), + mWidth(0), mHeight(0), mStride(0), mVStride(0), mFormat(format), mData(0), + mUsage(usage) +{ + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + common.incRef = incRef; + common.decRef = decRef; + android_native_buffer_t::getHandle = getHandlePriv; + if (w>0 && h>0) { + mInitCheck = initSize(w, h); + } +} + +Buffer::~Buffer() +{ + if (mBufferHandle) { + + gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module; + mod->unmap(mod, mBufferHandle); + + sAllocDev->free(sAllocDev, mBufferHandle); + } +} + +void Buffer::incRef(android_native_base_t* buffer) { + Buffer* self = static_cast<Buffer*>( + reinterpret_cast<android_native_buffer_t *>(buffer)); + self->incStrong(self); +} + +void Buffer::decRef(android_native_base_t* buffer) { + Buffer* self = static_cast<Buffer*>( + reinterpret_cast<android_native_buffer_t *>(buffer)); + self->decStrong(self); +} + +int Buffer::getHandlePriv(android_native_buffer_t const * buffer, + buffer_handle_t* handle) { + Buffer const * self = static_cast<Buffer const *>(buffer); + *handle = self->getHandle(); + return 0; +} + +status_t Buffer::initCheck() const { + return mInitCheck; +} + +android_native_buffer_t* Buffer::getNativeBuffer() const +{ + Buffer* that = const_cast<Buffer*>(this); + that->android_native_buffer_t::width = mWidth; + that->android_native_buffer_t::height = mHeight; + that->android_native_buffer_t::stride = mStride; + that->android_native_buffer_t::format = mFormat; + that->android_native_buffer_t::usage = mUsage; + that->android_native_buffer_t::bits = mData; + return static_cast<android_native_buffer_t*>(that); +} + +status_t Buffer::initSize(uint32_t w, uint32_t h) +{ + status_t err = NO_ERROR; + + int32_t stride; + err = sAllocDev->alloc(sAllocDev, w, h, mFormat, mUsage, &mBufferHandle, &stride); + + if (err == NO_ERROR) { + void* addr = 0; + gralloc_module_t* mod = (gralloc_module_t*)sAllocDev->common.module; + err = mod->map(mod, mBufferHandle, &addr); + if (err == NO_ERROR) { + mData = addr; + mWidth = w; + mHeight = h; + mStride = stride; + mVStride = 0; + } + } + + return err; +} + +void Buffer::setPixel(int x, int y, int r, int g, int b, int a) { + if (x < 0 || (unsigned int) x >= mWidth + || y < 0 || (unsigned int) y >= mHeight) { + // clipped + return; + } + int index = mStride * y + x; + switch (mFormat) { + case HAL_PIXEL_FORMAT_RGB_565: { + unsigned short val = (unsigned short) ( + ((0x1f & (r >> 3)) << 11) + | ((0x3f & (g >> 2)) << 5) + | (0x1f & (b >> 3))); + ((unsigned short*) mData)[index]= val; + } + break; + case HAL_PIXEL_FORMAT_RGBA_8888: { // ABGR + unsigned int val = (unsigned int) + (((a & 0xff) << 24) + | ((b & 0xff) << 16) + | ((g & 0xff) << 8) + | (r & 0xff)); + ((unsigned int*) mData)[index] = val; + } + break; + default: + // Unsupported pixel format + break; + } +} + + +static void gluLookAt(float eyeX, float eyeY, float eyeZ, + float centerX, float centerY, float centerZ, float upX, float upY, + float upZ) +{ + // See the OpenGL GLUT documentation for gluLookAt for a description + // of the algorithm. We implement it in a straightforward way: + + float fx = centerX - eyeX; + float fy = centerY - eyeY; + float fz = centerZ - eyeZ; + + // Normalize f + float rlf = 1.0f / sqrtf(fx*fx + fy*fy + fz*fz); + fx *= rlf; + fy *= rlf; + fz *= rlf; + + // Normalize up + float rlup = 1.0f / sqrtf(upX*upX + upY*upY + upZ*upZ); + upX *= rlup; + upY *= rlup; + upZ *= rlup; + + // compute s = f x up (x means "cross product") + + float sx = fy * upZ - fz * upY; + float sy = fz * upX - fx * upZ; + float sz = fx * upY - fy * upX; + + // compute u = s x f + float ux = sy * fz - sz * fy; + float uy = sz * fx - sx * fz; + float uz = sx * fy - sy * fx; + + float m[16] ; + m[0] = sx; + m[1] = ux; + m[2] = -fx; + m[3] = 0.0f; + + m[4] = sy; + m[5] = uy; + m[6] = -fy; + m[7] = 0.0f; + + m[8] = sz; + m[9] = uz; + m[10] = -fz; + m[11] = 0.0f; + + m[12] = 0.0f; + m[13] = 0.0f; + m[14] = 0.0f; + m[15] = 1.0f; + + glMultMatrixf(m); + glTranslatef(-eyeX, -eyeY, -eyeZ); +} + +int init_gralloc() { + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gralloc_module); + LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID); + + if (err == 0) { + gralloc_open(gralloc_module, &sAllocDev); + } + return err; +} + +int init_gl_surface(void) +{ + EGLint numConfigs = 1; + EGLConfig myConfig = {0}; + EGLint attrib[] = + { + EGL_DEPTH_SIZE, 16, + EGL_NONE + }; + + printf("init_gl_surface\n"); + if ( (eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY ) + { + printf("eglGetDisplay failed\n"); + return 0; + } + + if ( eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE ) + { + printf("eglInitialize failed\n"); + return 0; + } + + if ( eglChooseConfig(eglDisplay, attrib, &myConfig, 1, &numConfigs) != EGL_TRUE ) + { + printf("eglChooseConfig failed\n"); + return 0; + } + + if ( (eglSurface = eglCreateWindowSurface(eglDisplay, myConfig, + android_createDisplaySurface(), 0)) == EGL_NO_SURFACE ) + { + printf("eglCreateWindowSurface failed\n"); + return 0; + } + + if ( (eglContext = eglCreateContext(eglDisplay, myConfig, 0, 0)) == EGL_NO_CONTEXT ) + { + printf("eglCreateContext failed\n"); + return 0; + } + + if ( eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) != EGL_TRUE ) + { + printf("eglMakeCurrent failed\n"); + return 0; + } + + return 1; +} + +void free_gl_surface(void) +{ + if (eglDisplay != EGL_NO_DISPLAY) + { + eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT ); + eglDestroyContext( eglDisplay, eglContext ); + eglDestroySurface( eglDisplay, eglSurface ); + eglTerminate( eglDisplay ); + eglDisplay = EGL_NO_DISPLAY; + } +} + +void init_scene(void) +{ + glDisable(GL_DITHER); + glEnable(GL_CULL_FACE); + float ratio = 320.0f / 480.0f; + glViewport(0, 0, 320, 480); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustumf(-ratio, ratio, -1, 1, 1, 10); + + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + gluLookAt( + 0, 0, 3, // eye + 0, 0, 0, // center + 0, 1, 0); // up + + glEnable(GL_TEXTURE_2D); +} + +// #define USE_ALPHA_COLOR + +#define USE_GL_REPLACE +// #define USE_GL_MODULATE + +// #define USE_BLEND + +#define USE_565 +// #define USE_8888 + +// #define USE_NEAREST +#define USE_LINEAR + +#define USE_SCALE + +void setSmoothGradient(Buffer* bufferObject) { + int pixels = bufferObject->getHeight() * bufferObject->getWidth(); + int step = 0; + for (unsigned int y = 0; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + int grey = step * 255 / pixels; + bufferObject->setPixel(x, y, grey, grey, grey, 255); + ++step; + } + } +} + +void setSmoothAlphaGradient(Buffer* bufferObject) { + int pixels = bufferObject->getHeight() * bufferObject->getWidth(); + int step = 0; + for (unsigned int y = 0; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + int grey = step * 255 / pixels; + bufferObject->setPixel(x, y, 255, 255, 255, grey); + ++step; + } + } +} + +void setOrientedCheckerboard(Buffer* bufferObject) { + bufferObject->setPixel(0, 0, 0, 0, 0, 255); + for(unsigned int x = 1; x < bufferObject->getWidth() ; x++) { + bufferObject->setPixel(x, 0, 0, 255, 0, 255); + } + for (unsigned int y = 1; y < bufferObject->getHeight(); y++) { + for(unsigned int x = 0; x < bufferObject->getWidth() ; x++) { + if ((x ^ y ) & 1) { + bufferObject->setPixel(x, y, 255, 255, 255, 255); + } else { + bufferObject->setPixel(x, y, 255, 0, 0, 255); + } + } + } +} + +int create_physical_texture(unsigned int w, unsigned int h) +{ + +#ifdef USE_565 + PixelFormat format = HAL_PIXEL_FORMAT_RGB_565; +#else + PixelFormat format = HAL_PIXEL_FORMAT_RGBA_8888; +#endif + int usage = GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_HW_2D; /* This is the key to allocating the texture in pmem. */ + int32_t stride; + buffer_handle_t handle; + + // Allocate the hardware buffer + Buffer* bufferObject = new Buffer(w, h, format, usage); + + android_native_buffer_t* buffer = bufferObject->getNativeBuffer(); + + buffer->common.incRef(&buffer->common); + + // create the new EGLImageKHR + EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_NONE }; + EGLDisplay dpy = eglGetCurrentDisplay(); + EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + (EGLClientBuffer)buffer, attrs); + if (image == EGL_NO_IMAGE_KHR) { + printf("Could not create an image %d\n", eglGetError()); + return -1; + } + + if (buffer->bits == NULL) { + printf("No bits allocated for image.\n"); + return -2; + } + + setOrientedCheckerboard(bufferObject); + // setSmoothGradient(bufferObject); + // setSmoothAlphaGradient(bufferObject); + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); +#ifdef USE_LINEAR + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +#elif defined(USE_NEAREST) + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +#endif + +#ifdef USE_GL_REPLACE + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +#elif defined(USE_GL_MODULATE) + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#endif + +#ifdef USE_ALPHA_COLOR + glColor4f(1.0f, 1.0f, 1.0f, 0.4f); +#else + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); +#endif + +#ifdef USE_BLEND + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif + return 0; +} + +static const int SCALE_COUNT = 12; + +int scale(int base, int factor) { + static const float kTable[SCALE_COUNT] = { + 0.1f, 0.25f, 0.5f, 0.75f, 1.0f, + 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 5.0f + }; + return base * kTable[factor]; +} + +class Timer { + struct timeval first; + double elapsedSeconds; + +public: + Timer() {} + void start() { + gettimeofday(&first, NULL); + } + + void stop() { + struct timeval second, + elapsed; + gettimeofday(&second, NULL); + + if (first.tv_usec > second.tv_usec) { + second.tv_usec += 1000000; + second.tv_sec--; + } + + elapsedSeconds = (second.tv_sec - first.tv_sec) + + (second.tv_usec - first.tv_usec) / 1000000.0; + } + + double getElapsedSeconds() { + return elapsedSeconds; + } + + double getElapsedMs() { + return elapsedSeconds* 1000.0f; + } +}; + +int testTime() +{ + static const int WIDTH = 320; + static const int HEIGHT = 480; + static const int SCALE = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 1.0, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + +#if defined(USE_SCALE) + static const int scaleOffset = 0; +#else + static const int scaleOffset = 1; +#endif + printf("ms\n"); + for(int j = 0; j < SCALE; j++) { + int w = WIDTH >> (j + scaleOffset); + int h = HEIGHT >> j; + int cropRect[4] = {0,h,w,-h}; // Left bottom width height. Width and Height can be neg to flip. + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); + Timer timer; + timer.start(); + + int copyCount = 1000; + for (int i = 0; i < copyCount; i++) { + glDrawTexiOES(0, 0, 0, w, h); + } + + timer.stop(); + printf("%g\n", timer.getElapsedMs() / copyCount); + } + + eglSwapBuffers(eglDisplay, eglSurface); + return 0; +} + +int testStretch() +{ + static const int WIDTH = 8; + static const int HEIGHT = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 1.0, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + int cropRect[4] = {0,HEIGHT,WIDTH,-HEIGHT}; // Left bottom width height. Width and Height can be neg to flip. + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); + + for(int frame = 0; frame < 2; frame++) { + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + int baseX = 10; + for (int x = 0; x < SCALE_COUNT; x++) { + int baseY = 10; + int width = scale(WIDTH, x); + for (int y = 0; y < SCALE_COUNT; y++) { + int height = scale(HEIGHT, y); + glDrawTexxOES(baseX << 16, baseY << 16, 0, width << 16, height << 16); + baseY += height + 10; + } + baseX += width + 10; + } + + eglSwapBuffers(eglDisplay, eglSurface); + } + return 0; +} + +int testRot90() +{ + static const int WIDTH = 8; + static const int HEIGHT = 8; + + if (create_physical_texture(WIDTH, HEIGHT) != 0) { + return -1; + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrthof(0, 320, 480, 0, 0, 1); + + glMatrixMode(GL_MODELVIEW); + + glLoadIdentity(); + + // Need to do a dummy eglSwapBuffers first. Don't know why. + glClearColor(0.4, 0.4, 0.4, 0.4); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + eglSwapBuffers(eglDisplay, eglSurface); + + glEnable(GL_TEXTURE_2D); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glColor4x(0x10000, 0x10000, 0x10000, 0x10000); + glDisable(GL_BLEND); + glShadeModel(GL_FLAT); + glDisable(GL_DITHER); + glDisable(GL_CULL_FACE); + + for(int frame = 0; frame < 2; frame++) { + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + int baseX = 10; + for (int x = 0; x < SCALE_COUNT; x++) { + int baseY = 10; + int width = scale(WIDTH, x); + for (int y = 0; y < SCALE_COUNT; y++) { + int height = scale(HEIGHT, y); + + // Code copied from SurfaceFlinger LayerBase.cpp + + const GLfixed texCoords[4][2] = { + { 0, 0 }, + { 0, 0x10000 }, + { 0x10000, 0x10000 }, + { 0x10000, 0 } + }; + + GLfixed fx = baseX << 16; + GLfixed fy = baseY << 16; + GLfixed fw = width << 16; + GLfixed fh = height << 16; + + /* + * Vertex pattern: + * (2)--(3) + * |\ | + * | \ | + * | \ | + * | \| + * (1)--(0) + * + */ + + const GLfixed vertices[4][2] = { + {fx + fw, fy}, + {fx, fy}, + {fx, fy + fh}, + {fx + fw, fy + fh} + }; + + static const bool rotate90 = true; + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FIXED, 0, vertices); + glTexCoordPointer(2, GL_FIXED, 0, texCoords); + + LOGW("testRot90 %d, %d %d, %d", baseX, baseY, width, height); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + baseY += height + 10; + } + baseX += width + 10; + } + + eglSwapBuffers(eglDisplay, eglSurface); + } + return 0; +} + +int main(int argc, char **argv) +{ + + int q; + int start, end; + + if (init_gralloc()) { + printf("gralloc initialization failed - exiting\n"); + return 0; + } + + printf("Initializing EGL...\n"); + + if(!init_gl_surface()) + { + printf("GL initialisation failed - exiting\n"); + return 0; + } + + init_scene(); + + printf("Start test...\n"); + // testTime(); + // testStretch(); + testRot90(); + free_gl_surface(); + + return 0; +} |