Merge commit 'goog/master_gl' into merge_master_gl

This commit is contained in:
Mathias Agopian
2009-07-06 14:52:04 -07:00
139 changed files with 10893 additions and 5217 deletions

View File

@@ -12,6 +12,8 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
endif
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \

View File

@@ -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(),

View File

@@ -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;
};
// ---------------------------------------------------------------------------

View File

@@ -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();
}

View File

@@ -19,6 +19,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 \

View File

@@ -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;");

View File

@@ -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;
}

0
core/res/res/drawable/stat_sys_signal_flightmode.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 898 B

After

Width:  |  Height:  |  Size: 898 B

View File

@@ -78,6 +78,8 @@ status_t getService(const String16& name, sp<INTERFACE>* outService)
bool checkCallingPermission(const String16& permission);
bool checkCallingPermission(const String16& permission,
int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
// ----------------------------------------------------------------------

View File

@@ -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) {

View File

@@ -0,0 +1,68 @@
/*
* 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 BINDER_PERMISSION_H
#define BINDER_PERMISSION_H
#include <stdint.h>
#include <unistd.h>
#include <utils/SortedVector.h>
#include <utils/String16.h>
#include <utils/threads.h>
namespace android {
// ---------------------------------------------------------------------------
/*
* Permission caches the result of the permission check for the given
* permission name and the provided uid/pid. It also handles a few
* known cases efficiently (caller is in the same process or is root).
* The package manager does something similar but lives in dalvik world
* and is therefore extremely slow to access.
*/
class Permission
{
public:
Permission(char const* name);
Permission(const String16& name);
Permission(const Permission& rhs);
virtual ~Permission();
bool operator < (const Permission& rhs) const;
// checks the current binder call's caller has access to this permission
bool checkCalling() const;
// checks the specified pid/uid has access to this permission
bool check(pid_t pid, uid_t uid) const;
protected:
virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
private:
Permission& operator = (const Permission& rhs) const;
const String16 mPermissionName;
mutable SortedVector<uid_t> mGranted;
const pid_t mPid;
mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif /* BINDER_PERMISSION_H */

View File

@@ -26,6 +26,8 @@
#endif
#include <private/pixelflinger/ggl_context.h>
#include <hardware/copybit.h>
#include <hardware/gralloc.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
@@ -39,7 +41,7 @@ class EGLSurfaceManager;
class EGLBufferObjectManager;
namespace gl {
struct ogles_context_t;
struct matrixx_t;
struct transform_t;
@@ -96,7 +98,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 +108,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 +123,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 +132,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 +144,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 +201,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 +412,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 +511,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 +596,14 @@ 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;
buffer_handle_t drawSurfaceBuffer;
};
struct ogles_context_t {
context_t rasterizer;
array_machine_t arrays __attribute__((aligned(32)));
@@ -617,6 +627,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() {

View File

@@ -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 */

View File

@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <utils/Debug.h>
#include <utils/threads.h>
namespace android {
@@ -32,16 +33,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 +107,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,30 +133,19 @@ 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];
};
// ---------------------------------------------------------------------------
template<bool> struct CTA;
template<> struct CTA<true> { };
// compile-time assertions. just to avoid catastrophes.
inline void compile_time_asserts() {
CTA<sizeof(layer_cblk_t) == 128> sizeof__layer_cblk_t__eq_128;
(void)sizeof__layer_cblk_t__eq_128; // we don't want a warning
CTA<sizeof(per_client_cblk_t) <= 4096> sizeof__per_client_cblk_t__le_4096;
(void)sizeof__per_client_cblk_t__le_4096; // we don't want a warning
CTA<sizeof(surface_flinger_cblk_t) <= 4096> sizeof__surface_flinger_cblk_t__le_4096;
(void)sizeof__surface_flinger_cblk_t__le_4096; // we don't want a warning
}
COMPILE_TIME_ASSERT(sizeof(layer_cblk_t) == 128)
COMPILE_TIME_ASSERT(sizeof(per_client_cblk_t) <= 4096)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_UI_SHARED_STATE_H

View File

@@ -0,0 +1,77 @@
/*
* 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 Parcel;
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

View File

@@ -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

View File

@@ -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 */

64
include/ui/BufferMapper.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -32,7 +32,6 @@ namespace android {
// ----------------------------------------------------------------------------
class DisplayInfo;
class IGPUCallback;
class ISurfaceComposer : public IInterface
{
@@ -63,7 +62,6 @@ public:
eTransparentRegionChanged = 0x00000020,
eVisibilityChanged = 0x00000040,
eFreezeTintChanged = 0x00000080,
eDestroyed = 0x00000100
};
enum {
@@ -94,7 +92,7 @@ public:
virtual sp<ISurfaceFlingerClient> createConnection() = 0;
/* retrieve the control block */
virtual sp<IMemory> getCblk() const = 0;
virtual sp<IMemoryHeap> getCblk() const = 0;
/* open/close transactions. recquires ACCESS_SURFACE_FLINGER permission */
virtual void openGlobalTransaction() = 0;
@@ -112,37 +110,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 +132,6 @@ public:
SET_ORIENTATION,
FREEZE_DISPLAY,
UNFREEZE_DISPLAY,
REQUEST_GPU,
REVOKE_GPU,
SIGNAL
};
@@ -170,15 +141,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

View File

@@ -52,12 +52,11 @@ 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;
};
virtual void getControlBlocks(sp<IMemory>* ctl) const = 0;
virtual sp<IMemoryHeap> getControlBlock() const = 0;
virtual sp<ISurface> createSurface( surface_data_t* data,
int pid,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,78 @@ public:
Region& operator = (const Region& rhs);
inline bool isEmpty() const { return mRegion.isEmpty(); }
inline bool isRect() const { return mRegion.isRect(); }
inline bool isEmpty() const { return mBounds.isEmpty(); }
inline bool isRect() const { return mStorage.isEmpty(); }
Rect bounds() const;
const SkRegion& toSkRegion() const;
inline Rect getBounds() const { return mBounds; }
inline Rect bounds() const { return getBounds(); }
// the region becomes its bounds
Region& makeBoundsSelf();
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 +133,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 +193,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

View File

@@ -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,10 +75,103 @@ 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
friend class Camera;
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; }
friend class Surface;
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);
~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; }
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);
Surface(const sp<SurfaceControl>& control);
void init();
~Surface();
friend class SurfaceComposerClient;
friend class SurfaceControl;
// camera and camcorder need access to the ISurface binder interface for preview
friend class Camera;
friend class MediaRecorder;
@@ -95,40 +180,43 @@ private:
friend class Test;
const sp<ISurface>& getISurface() const { return mSurface; }
// can't be copied
Surface& operator = (Surface& rhs);
Surface(const Surface& rhs);
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);
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 = true);
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);
Surface(Surface const* rhs);
int dequeueBuffer(android_native_buffer_t** buffer);
int lockBuffer(android_native_buffer_t* buffer);
int queueBuffer(android_native_buffer_t* buffer);
~Surface();
Region dirtyRegion() const;
void setDirtyRegion(const Region& region) const;
// this locks protects calls to lockSurface() / unlockSurface()
// and is called by SurfaceComposerClient.
Mutex& getLock() const { return mSurfaceLock; }
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

View File

@@ -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;
@@ -165,11 +149,8 @@ private:
// after assignment
status_t mStatus;
per_client_cblk_t* mControl;
sp<IMemory> mControlMemory;
sp<IMemoryHeap> mControlMemory;
sp<ISurfaceFlingerClient> mClient;
sp<IMemoryHeap> mSurfaceHeap;
uint8_t* mSurfaceHeapBase;
void* mGL;
SurfaceFlingerSynchro* mSignalServer;
};

View File

@@ -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 */

View File

@@ -14,10 +14,6 @@
* limitations under the License.
*/
//
// Debugging tools. These should be able to be stripped
// in release builds.
//
#ifndef ANDROID_DEBUG_H
#define ANDROID_DEBUG_H
@@ -25,9 +21,30 @@
#include <sys/types.h>
namespace android {
// ---------------------------------------------------------------------------
#ifdef __cplusplus
template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true> {};
#define COMPILE_TIME_ASSERT(_exp) \
template class CompileTimeAssert< (_exp) >;
#endif
// ---------------------------------------------------------------------------
#ifdef __cplusplus
template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
template<typename LHS, typename RHS>
struct CompileTimeIfElse<true, LHS, RHS> { typedef LHS TYPE; };
template<typename LHS, typename RHS>
struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
#endif
// ---------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
const char* stringForIndent(int32_t indentLevel);
@@ -35,11 +52,17 @@ typedef void (*debugPrintFunc)(void* cookie, const char* txt);
void printTypeCode(uint32_t typeCode,
debugPrintFunc func = 0, void* cookie = 0);
void printHexData(int32_t indent, const void *buf, size_t length,
size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
size_t alignment=0, bool cArrayStyle=false,
debugPrintFunc func = 0, void* cookie = 0);
#ifdef __cplusplus
}
#endif
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_DEBUG_H

View File

@@ -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;

View File

@@ -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
#include <stddef.h>
#include <stdint.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; }
_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;
};
/*
* Iterator for walking through the list.
*/
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(); }
/*
* Iterator comparison.
*/
bool operator==(const _Iter& right) const { return mpNode == right.mpNode; }
bool operator!=(const _Iter& right) const { return mpNode != right.mpNode; }
/*
* Incr/decr, used to move 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;
}
_Node* getNode(void) const { return mpNode; }
private:
_Node* 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;
template<typename T>
class List
{
protected:
/*
* One element in the list.
*/
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;
};
List(void) {
/*
* Iterator for walking through the list.
*/
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;
}
inline _NodePtr getNode() const { return mpNode; }
private:
friend class List;
_NodePtr mpNode;
};
public:
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);

View File

@@ -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() { }

69
include/utils/Singleton.h Normal file
View File

@@ -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

View File

@@ -141,8 +141,7 @@ SortedVector<TYPE>::SortedVector()
: SortedVectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0)
|(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
)
{
}

View File

@@ -29,35 +29,39 @@ namespace android {
/*
* Types traits
*/
template <typename T> struct trait_trivial_ctor { enum { value = false }; };
template <typename T> struct trait_trivial_dtor { enum { value = false }; };
template <typename T> struct trait_trivial_copy { enum { value = false }; };
template <typename T> struct trait_trivial_assign{ enum { value = false }; };
template <typename T> struct trait_pointer { enum { value = false }; };
template <typename T> struct trait_pointer<T*> { enum { value = true }; };
template <typename T> struct trait_trivial_ctor { enum { value = false }; };
template <typename T> struct trait_trivial_dtor { enum { value = false }; };
template <typename T> struct trait_trivial_copy { enum { value = false }; };
template <typename T> struct trait_trivial_move { enum { value = false }; };
template <typename T> struct trait_pointer { enum { value = false }; };
template <typename T> struct trait_pointer<T*> { enum { value = true }; };
#define ANDROID_BASIC_TYPES_TRAITS( T ) \
template<> struct trait_trivial_ctor< T > { enum { value = true }; }; \
template<> struct trait_trivial_dtor< T > { enum { value = true }; }; \
template<> struct trait_trivial_copy< T > { enum { value = true }; }; \
template<> struct trait_trivial_assign< T >{ enum { value = true }; };
// sp<> can be trivially moved
template <typename T> class sp;
template <typename T> struct trait_trivial_move< sp<T> >{
enum { value = true };
};
#define ANDROID_TYPE_TRAITS( T, ctor, dtor, copy, assign ) \
template<> struct trait_trivial_ctor< T > { enum { value = ctor }; }; \
template<> struct trait_trivial_dtor< T > { enum { value = dtor }; }; \
template<> struct trait_trivial_copy< T > { enum { value = copy }; }; \
template<> struct trait_trivial_assign< T >{ enum { value = assign }; };
// wp<> can be trivially moved
template <typename T> class wp;
template <typename T> struct trait_trivial_move< wp<T> >{
enum { value = true };
};
template <typename TYPE>
struct traits {
enum {
// whether this type is a pointer
is_pointer = trait_pointer<TYPE>::value,
// whether this type's constructor is a no-op
has_trivial_ctor = is_pointer || trait_trivial_ctor<TYPE>::value,
// whether this type's destructor is a no-op
has_trivial_dtor = is_pointer || trait_trivial_dtor<TYPE>::value,
// whether this type type can be copy-constructed with memcpy
has_trivial_copy = is_pointer || trait_trivial_copy<TYPE>::value,
has_trivial_assign = is_pointer || trait_trivial_assign<TYPE>::value
// whether this type can be moved with memmove
has_trivial_move = is_pointer || trait_trivial_move<TYPE>::value
};
};
@@ -65,37 +69,47 @@ template <typename T, typename U>
struct aggregate_traits {
enum {
is_pointer = false,
has_trivial_ctor = traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
has_trivial_dtor = traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
has_trivial_copy = traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
has_trivial_assign = traits<T>::has_trivial_assign && traits<U>::has_trivial_assign
has_trivial_ctor =
traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
has_trivial_dtor =
traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
has_trivial_copy =
traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
has_trivial_move =
traits<T>::has_trivial_move && traits<U>::has_trivial_move
};
};
#define ANDROID_BASIC_TYPES_TRAITS( T ) \
template<> struct trait_trivial_ctor< T > { enum { value = true }; }; \
template<> struct trait_trivial_dtor< T > { enum { value = true }; }; \
template<> struct trait_trivial_copy< T > { enum { value = true }; }; \
template<> struct trait_trivial_move< T > { enum { value = true }; };
// ---------------------------------------------------------------------------
/*
* basic types traits
*/
ANDROID_BASIC_TYPES_TRAITS( void );
ANDROID_BASIC_TYPES_TRAITS( bool );
ANDROID_BASIC_TYPES_TRAITS( char );
ANDROID_BASIC_TYPES_TRAITS( unsigned char );
ANDROID_BASIC_TYPES_TRAITS( short );
ANDROID_BASIC_TYPES_TRAITS( unsigned short );
ANDROID_BASIC_TYPES_TRAITS( int );
ANDROID_BASIC_TYPES_TRAITS( unsigned int );
ANDROID_BASIC_TYPES_TRAITS( long );
ANDROID_BASIC_TYPES_TRAITS( unsigned long );
ANDROID_BASIC_TYPES_TRAITS( long long );
ANDROID_BASIC_TYPES_TRAITS( unsigned long long );
ANDROID_BASIC_TYPES_TRAITS( float );
ANDROID_BASIC_TYPES_TRAITS( double );
ANDROID_BASIC_TYPES_TRAITS( void )
ANDROID_BASIC_TYPES_TRAITS( bool )
ANDROID_BASIC_TYPES_TRAITS( char )
ANDROID_BASIC_TYPES_TRAITS( unsigned char )
ANDROID_BASIC_TYPES_TRAITS( short )
ANDROID_BASIC_TYPES_TRAITS( unsigned short )
ANDROID_BASIC_TYPES_TRAITS( int )
ANDROID_BASIC_TYPES_TRAITS( unsigned int )
ANDROID_BASIC_TYPES_TRAITS( long )
ANDROID_BASIC_TYPES_TRAITS( unsigned long )
ANDROID_BASIC_TYPES_TRAITS( long long )
ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
ANDROID_BASIC_TYPES_TRAITS( float )
ANDROID_BASIC_TYPES_TRAITS( double )
// ---------------------------------------------------------------------------
/*
* compare and order types
*/
@@ -111,9 +125,9 @@ int compare_type(const TYPE& lhs, const TYPE& rhs) {
}
/*
* create, destroy, copy and assign types...
* create, destroy, copy and move types...
*/
template<typename TYPE> inline
void construct_type(TYPE* p, size_t n) {
if (!traits<TYPE>::has_trivial_ctor) {
@@ -145,17 +159,6 @@ void copy_type(TYPE* d, const TYPE* s, size_t n) {
}
}
template<typename TYPE> inline
void assign_type(TYPE* d, const TYPE* s, size_t n) {
if (!traits<TYPE>::has_trivial_assign) {
while (n--) {
*d++ = *s++;
}
} else {
memcpy(d,s,n*sizeof(TYPE));
}
}
template<typename TYPE> inline
void splat_type(TYPE* where, const TYPE* what, size_t n) {
if (!traits<TYPE>::has_trivial_copy) {
@@ -164,15 +167,19 @@ void splat_type(TYPE* where, const TYPE* what, size_t n) {
where++;
}
} else {
while (n--) {
*where++ = *what;
while (n--) {
*where++ = *what;
}
}
}
template<typename TYPE> inline
void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
|| traits<TYPE>::has_trivial_move)
{
memmove(d,s,n*sizeof(TYPE));
} else {
d += n;
s += n;
while (n--) {
@@ -180,35 +187,37 @@ void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
if (!traits<TYPE>::has_trivial_copy) {
new(d) TYPE(*s);
} else {
*d = *s;
*d = *s;
}
if (!traits<TYPE>::has_trivial_dtor) {
s->~TYPE();
}
}
} else {
memmove(d,s,n*sizeof(TYPE));
}
}
template<typename TYPE> inline
void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
if (!traits<TYPE>::has_trivial_copy || !traits<TYPE>::has_trivial_dtor) {
if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy)
|| traits<TYPE>::has_trivial_move)
{
memmove(d,s,n*sizeof(TYPE));
} else {
while (n--) {
if (!traits<TYPE>::has_trivial_copy) {
new(d) TYPE(*s);
} else {
*d = *s;
*d = *s;
}
if (!traits<TYPE>::has_trivial_dtor) {
s->~TYPE();
}
d++, s++;
}
} else {
memmove(d,s,n*sizeof(TYPE));
}
}
// ---------------------------------------------------------------------------
/*
@@ -242,8 +251,8 @@ struct trait_trivial_copy< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
template<>
template <typename K, typename V>
struct trait_trivial_assign< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_assign};};
struct trait_trivial_move< key_value_pair_t<K, V> >
{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
// ---------------------------------------------------------------------------

View File

@@ -175,8 +175,7 @@ Vector<TYPE>::Vector()
: VectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0)
|(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
)
{
}

View File

@@ -44,7 +44,6 @@ public:
HAS_TRIVIAL_CTOR = 0x00000001,
HAS_TRIVIAL_DTOR = 0x00000002,
HAS_TRIVIAL_COPY = 0x00000004,
HAS_TRIVIAL_ASSIGN = 0x00000008
};
VectorImpl(size_t itemSize, uint32_t flags);

View File

@@ -29,6 +29,7 @@ LOCAL_SRC_FILES:= \
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
Permission.cpp \
ProcessState.cpp \
Static.cpp

View File

@@ -19,8 +19,8 @@
#include <binder/IServiceManager.h>
#include <utils/Debug.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
@@ -53,14 +53,19 @@ bool checkCallingPermission(const String16& permission)
static String16 _permission("permission");
bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{
IPCThreadState* ipcState = IPCThreadState::self();
int32_t pid = ipcState->getCallingPid();
int32_t uid = ipcState->getCallingUid();
pid_t pid = ipcState->getCallingPid();
uid_t uid = ipcState->getCallingUid();
if (outPid) *outPid = pid;
if (outUid) *outUid= uid;
if (outUid) *outUid = uid;
return checkPermission(permission, pid, uid);
}
bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
{
sp<IPermissionController> pc;
gDefaultServiceManagerLock.lock();
pc = gPermissionController;

View File

@@ -0,0 +1,88 @@
/*
* 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 <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Permission.h>
namespace android {
// ---------------------------------------------------------------------------
Permission::Permission(char const* name)
: mPermissionName(name), mPid(getpid())
{
}
Permission::Permission(const String16& name)
: mPermissionName(name), mPid(getpid())
{
}
Permission::Permission(const Permission& rhs)
: mPermissionName(rhs.mPermissionName),
mGranted(rhs.mGranted),
mPid(rhs.mPid)
{
}
Permission::~Permission()
{
}
bool Permission::operator < (const Permission& rhs) const
{
return mPermissionName < rhs.mPermissionName;
}
bool Permission::checkCalling() const
{
IPCThreadState* ipcState = IPCThreadState::self();
pid_t pid = ipcState->getCallingPid();
uid_t uid = ipcState->getCallingUid();
return doCheckPermission(pid, uid);
}
bool Permission::check(pid_t pid, uid_t uid) const
{
return doCheckPermission(pid, uid);
}
bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
{
if ((uid == 0) || (pid == mPid)) {
// root and ourselves is always okay
return true;
} else {
// see if we already granted this permission for this uid
Mutex::Autolock _l(mLock);
if (mGranted.indexOf(uid) >= 0)
return true;
}
bool granted = checkPermission(mPermissionName, pid, uid);
if (granted) {
Mutex::Autolock _l(mLock);
// no need to check again, the old item will be replaced if it is
// already there.
mGranted.add(uid);
}
return granted;
}
// ---------------------------------------------------------------------------
}; // namespace android

View File

@@ -23,7 +23,6 @@
#include <math.h>
#include <utils/misc.h>
#include <ui/EGLNativeWindowSurface.h>
#include <ui/Surface.h>
#include <core/SkBitmap.h>

View File

@@ -18,6 +18,7 @@
#include "rsContext.h"
#include "rsThreadIO.h"
#include "utils/String8.h"
#include <ui/FramebufferNativeWindow.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
@@ -46,8 +47,7 @@ void Context::initEGL()
eglChooseConfig(mDisplay, s_configAttribs, &mConfig, 1, &mNumConfigs);
if (mWndSurface) {
mSurface = eglCreateWindowSurface(mDisplay, mConfig,
new EGLNativeWindowSurface(mWndSurface),
mSurface = eglCreateWindowSurface(mDisplay, mConfig, mWndSurface,
NULL);
} else {
mSurface = eglCreateWindowSurface(mDisplay, mConfig,

View File

@@ -17,6 +17,9 @@
#ifndef ANDROID_RS_CONTEXT_H
#define ANDROID_RS_CONTEXT_H
#include <utils/Vector.h>
#include <ui/Surface.h>
#include "rsType.h"
#include "rsMatrix.h"
#include "rsAllocation.h"
@@ -35,10 +38,6 @@
#include "rsgApiStructs.h"
#include "rsLocklessFifo.h"
#include <ui/EGLNativeWindowSurface.h>
#include <ui/Surface.h>
// ---------------------------------------------------------------------------
namespace android {

View File

@@ -5,23 +5,25 @@ 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
ifeq ($(TARGET_BOARD_PLATFORM), msm7k)
LOCAL_CFLAGS += -DDIM_WITH_TEXTURE
endif
# need "-lrt" on Linux simulator to pick up clock_gettime
ifeq ($(TARGET_SIMULATOR),true)
@@ -31,20 +33,21 @@ ifeq ($(TARGET_SIMULATOR),true)
endif
LOCAL_SHARED_LIBRARIES := \
libcutils \
libpixelflinger \
libhardware \
libutils \
libbinder \
libcutils \
libui \
libcorecg \
libsgl \
libpixelflinger \
libEGL \
libGLESv1_CM
libGLESv1_CM \
libbinder \
libui
LOCAL_C_INCLUDES := \
$(call include-path-for, corecg graphics)
LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
LOCAL_MODULE:= libsurfaceflinger
include $(BUILD_SHARED_LIBRARY)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,32 @@ 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];
break;
}
}
}
delete [] configs;
/*
* Gather EGL extensions
@@ -145,12 +184,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 +198,29 @@ 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("eglCreateWindowSurface");
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;
#ifdef EGL_ANDROID_swap_rectangle
if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
mFlags |= SWAP_RECTANGLE;
}
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;
}
mRefreshRate = 60.f; // TODO: get the real refresh rate
// when we have the choice between UPDATE_ON_DEMAND and SWAP_RECTANGLE
// choose UPDATE_ON_DEMAND, which is more efficient
if (mFlags & UPDATE_ON_DEMAND)
mFlags &= ~SWAP_RECTANGLE;
#endif
mDpiX = mNativeWindow->xdpi;
mDpiX = mNativeWindow->ydpi;
mRefreshRate = fbDev->fps;
char property[PROPERTY_VALUE_MAX];
/* Read density from build-specific ro.sf.lcd_density property
@@ -230,7 +264,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;
}
@@ -241,19 +278,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;
}
/*
@@ -267,7 +293,6 @@ void DisplayHardware::fini()
{
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mDisplay);
copybit_close(mBlitEngine);
overlay_control_close(mOverlayEngine);
}
@@ -281,28 +306,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;
}
/*
@@ -316,21 +321,20 @@ 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) {
const Rect& b(newDirty.bounds());
mDisplaySurface->setSwapRectangle(
#ifdef EGL_ANDROID_swap_rectangle
if (mFlags & SWAP_RECTANGLE) {
const Region newDirty(dirty.intersect(bounds()));
const Rect b(newDirty.getBounds());
eglSetSwapRectangleANDROID(dpy, surface,
b.left, b.top, b.width(), b.height());
}
#endif
if (mFlags & UPDATE_ON_DEMAND) {
mNativeWindow->setUpdateRectangle(dirty.getBounds());
}
mPageFlipCount++;
eglSwapBuffers(dpy, surface);
checkEGLErrors("eglSwapBuffers");
@@ -348,11 +352,3 @@ void DisplayHardware::makeCurrent() const
{
eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
}
void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const {
mDisplaySurface->copyFrontToImage(front);
}
void DisplayHardware::copyBackToImage(const copybit_image_t& front) const {
mDisplaySurface->copyBackToImage(front);
}

View File

@@ -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,15 +77,9 @@ 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;
void copyBackToImage(const copybit_image_t& front) const;
Rect bounds() const {
return Rect(mWidth, mHeight);
}
@@ -102,9 +100,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;
};

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <assert.h>
#include <errno.h>
#include <stdlib.h>

View File

@@ -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"
@@ -49,13 +47,12 @@ const char* const Layer::typeID = "Layer";
// ---------------------------------------------------------------------------
Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i)
: LayerBaseClient(flinger, display, c, 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,12 +60,25 @@ 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;
}
mBuffers[i].free();
}
mSurface.clear();
}
void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
@@ -79,148 +89,206 @@ 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::setBuffers( Client* client,
uint32_t w, uint32_t h,
status_t Layer::ditch()
{
// the layer is not on screen anymore. free as much resources as possible
destroy();
return NO_ERROR;
}
status_t Layer::setBuffers( uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags)
{
PixelFormatInfo info;
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;
mTextures[index].width = clientBuf->width;
mTextures[index].height = clientBuf->height;
}
}
}
} 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(&mTextures[0], mTextures[0].name, dirty, t);
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.
clearWithOpenGL(clip);
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);
}
drawWithOpenGL(clip, mTextures[index]);
}
status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
sp<SurfaceBuffer> Layer::peekBuffer()
{
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()));
/*
* 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.
*/
status_t err = mBuffers[index].resize(w, h);
if (err == NO_ERROR) {
mBuffers[index].getInfo(lcblk->surface + index);
} 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?
// 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,
"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 {
// 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 buffer;
}
void Layer::scheduleBroadcast()
{
sp<Client> ourClient(client.promote());
if (ourClient != 0) {
mFlinger->scheduleBroadcast(ourClient);
}
return err;
}
uint32_t Layer::doTransaction(uint32_t flags)
@@ -232,7 +300,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 +344,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 +367,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,10 +382,11 @@ 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);
scheduleBroadcast();
mResizeTransactionDone = true;
// we're being resized and there is a freeze display request,
@@ -353,14 +422,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 +442,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;
}
@@ -415,7 +495,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
if (UNLIKELY(state & eInvalidSurface)) {
// if eInvalidSurface is set, this means the surface
// became invalid during a transaction (NO_MEMORY for instance)
mFlinger->scheduleBroadcast(client);
scheduleBroadcast();
return;
}
@@ -457,15 +537,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 +562,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 +608,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(
@@ -547,7 +633,7 @@ void Layer::unlockPageFlip(
// client could be blocked, so signal them so they get a
// chance to reevaluate their condition.
mFlinger->scheduleBroadcast(client);
scheduleBroadcast();
}
}
@@ -558,9 +644,30 @@ void Layer::finishPageFlip()
"layer %p wasn't locked!", this);
android_atomic_and(~eBusy, &(lcblk->swapState));
}
mFlinger->scheduleBroadcast(client);
scheduleBroadcast();
}
// ---------------------------------------------------------------------------
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;
}
// ---------------------------------------------------------------------------

View File

@@ -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"
@@ -37,11 +42,12 @@ namespace android {
class Client;
class LayerBitmap;
class MemoryDealer;
class FreezeLock;
// ---------------------------------------------------------------------------
const int NUM_BUFFERS = 2;
class Layer : public LayerBaseClient
{
public:
@@ -51,16 +57,15 @@ public:
virtual uint32_t getTypeInfo() const { return typeInfo; }
Layer(SurfaceFlinger* flinger, DisplayID display,
Client* c, int32_t i);
const sp<Client>& client, int32_t i);
virtual ~Layer();
inline PixelFormat pixelFormat() const {
return frontBuffer().pixelFormat();
return frontBuffer().getPixelFormat();
}
status_t setBuffers( Client* client,
uint32_t w, uint32_t h,
status_t setBuffers( uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
virtual void onDraw(const Region& clip) const;
@@ -73,8 +78,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 +101,37 @@ 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();
void scheduleBroadcast();
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;
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;
};
// ---------------------------------------------------------------------------

View File

@@ -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,19 +53,13 @@ const char* const LayerBaseClient::typeID = "LayerBaseClient";
// ---------------------------------------------------------------------------
Vector<GLuint> LayerBase::deletedTextures;
int32_t LayerBase::sIdentity = 0;
LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: dpy(display), contentDirty(false),
mFlinger(flinger),
mTransformed(false),
mOrientation(0),
mCanUseCopyBit(false),
mTransactionFlags(0),
mPremultipliedAlpha(true),
mIdentity(uint32_t(android_atomic_inc(&sIdentity))),
mInvalidate(0)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
@@ -265,43 +259,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 +286,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 +296,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 +362,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);
@@ -416,15 +377,17 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
}
}
void LayerBase::drawWithOpenGL(const Region& clip,
GLint textureName, const GGLSurface& t, int transform) const
void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
{
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t fbHeight = hw.getHeight();
const State& s(drawingState());
// bind our texture
validateTexture(textureName);
validateTexture(texture.name);
uint32_t width = texture.width;
uint32_t height = texture.height;
glEnable(GL_TEXTURE_2D);
// Dithering...
@@ -472,8 +435,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) {
@@ -490,21 +454,23 @@ void LayerBase::drawWithOpenGL(const Region& clip,
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
if (transform == HAL_TRANSFORM_ROT_90) {
// the texture's source is rotated
if (texture.transform == HAL_TRANSFORM_ROT_90) {
// TODO: handle the other orientations
glTranslatef(0, 1, 0);
glRotatef(-90, 0, 0, 1);
}
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 +478,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 +492,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);
}
}
}
@@ -550,13 +517,16 @@ void LayerBase::validateTexture(GLint textureName) const
// this is currently done in loadTexture() below
}
void LayerBase::loadTexture(const Region& dirty,
GLint textureName, const GGLSurface& t,
GLuint& textureWidth, GLuint& textureHeight) const
void LayerBase::loadTexture(Texture* texture, GLint textureName,
const Region& dirty, const GGLSurface& t) const
{
// TODO: defer the actual texture reload until LayerBase::validateTexture
// is called.
texture->name = textureName;
GLuint& textureWidth(texture->width);
GLuint& textureHeight(texture->height);
uint32_t flags = mFlags;
glBindTexture(GL_TEXTURE_2D, textureName);
@@ -565,8 +535,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 +548,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,119 +565,98 @@ 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
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
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;
}
// ---------------------------------------------------------------------------
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
Client* c, int32_t i)
: LayerBase(flinger, display), client(c),
lcblk( c ? &(c->ctrlblk->layers[i]) : 0 ),
mIndex(i)
{
if (client) {
client->bindLayer(this, i);
int32_t LayerBaseClient::sIdentity = 0;
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
: LayerBase(flinger, display), client(client),
lcblk( client!=0 ? &(client->ctrlblk->layers[i]) : 0 ),
mIndex(i),
mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
}
void LayerBaseClient::onFirstRef()
{
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
// Initialize this layer's control block
memset(this->lcblk, 0, sizeof(layer_cblk_t));
this->lcblk->identity = mIdentity;
@@ -717,23 +667,121 @@ LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
LayerBaseClient::~LayerBaseClient()
{
if (client) {
sp<Client> client(this->client.promote());
if (client != 0) {
client->free(mIndex);
}
}
int32_t LayerBaseClient::serverIndex() const {
if (client) {
int32_t LayerBaseClient::serverIndex() const
{
sp<Client> client(this->client.promote());
if (client != 0) {
return (client->cid<<16)|mIndex;
}
return 0xFFFF0000 | mIndex;
}
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() const
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
{
return new Surface(clientIndex(), mIdentity);
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:
{
if (!mFlinger->mAccessSurfaceFlinger.checkCalling()) {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
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 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;
};
// ---------------------------------------------------------------------------

View File

@@ -20,8 +20,13 @@
#include <stdint.h>
#include <sys/types.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <private/ui/LayerState.h>
#include <utils/RefBase.h>
#include <ui/Region.h>
#include <ui/Overlay.h>
@@ -37,10 +42,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 +76,7 @@ public:
}
static Vector<GLuint> deletedTextures;
LayerBase(SurfaceFlinger* flinger, DisplayID display);
virtual ~LayerBase();
DisplayID dpy;
mutable bool contentDirty;
@@ -201,21 +205,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;
}
@@ -229,20 +241,24 @@ protected:
GLuint createTexture() const;
void drawWithOpenGL(const Region& clip,
GLint textureName,
const GGLSurface& surface,
int transform = 0) const;
void clearWithOpenGL(const Region& clip) const;
void loadTexture(const Region& dirty,
GLint textureName, const GGLSurface& t,
GLuint& textureWidth, GLuint& textureHeight) const;
bool canUseCopybit() const;
struct Texture {
Texture() : name(-1U), width(0), height(0),
image(EGL_NO_IMAGE_KHR), transform(0), dirty(true) { }
GLuint name;
GLuint width;
GLuint height;
EGLImageKHR image;
uint32_t transform;
bool dirty;
};
SurfaceFlinger* mFlinger;
void clearWithOpenGL(const Region& clip) const;
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
void loadTexture(Texture* texture, GLint textureName,
const Region& dirty, const GGLSurface& t) const;
sp<SurfaceFlinger> mFlinger;
uint32_t mFlags;
// cached during validateVisibility()
@@ -250,7 +266,6 @@ protected:
int32_t mOrientation;
GLfixed mVertices[4][2];
Rect mTransformedBounds;
bool mCanUseCopyBit;
int mLeft;
int mTop;
@@ -262,16 +277,16 @@ protected:
// don't change, don't need a lock
bool mPremultipliedAlpha;
// only read
const uint32_t mIdentity;
// atomic
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;
};
@@ -287,66 +302,63 @@ public:
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i);
const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
virtual void onFirstRef();
Client* const client;
wp<Client> 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;
}
ISurfaceFlingerClient::surface_data_t* params) const;
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;
};
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;
// only read
const uint32_t mIdentity;
static int32_t sIdentity;
};
// ---------------------------------------------------------------------------

View File

@@ -14,173 +14,196 @@
* 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
// ===========================================================================
Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
: SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags),
mVStride(0)
{
this->format = format;
if (w>0 && h>0) {
mInitCheck = initSize(w, h);
}
}
Buffer::~Buffer()
{
if (handle) {
BufferAllocator& allocator(BufferAllocator::get());
allocator.free(handle);
}
}
status_t Buffer::initCheck() const {
return mInitCheck;
}
android_native_buffer_t* Buffer::getNativeBuffer() const
{
return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
}
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
*
*/
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 {
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;
}
}
err = allocator.alloc(w, h, format, usage, &handle, &stride);
if (err == NO_ERROR) {
if (err == NO_ERROR) {
width = w;
height = h;
mVStride = 0;
}
}
return err;
}
status_t Buffer::lock(GGLSurface* sur, uint32_t usage)
{
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;
}
// ===========================================================================
// LayerBitmap
// ===========================================================================
LayerBitmap::LayerBitmap()
: mAllocFlags(0), mOffset(0), mSize(-1U), mAlignment(2)
: mInfo(0), mWidth(0), mHeight(0)
{
memset(&mSurface, 0, sizeof(mSurface));
}
LayerBitmap::~LayerBitmap()
{
mSurface.data = 0;
}
status_t LayerBitmap::init(const sp<MemoryDealer>& allocator)
status_t LayerBitmap::init(surface_info_t* info,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
{
if (mAllocator != NULL)
if (info == NULL)
return BAD_VALUE;
mAllocator = allocator;
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;
}
status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment,
PixelFormat format, uint32_t flags)
status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
{
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);
}
/* 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)
*/
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;
} 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 (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;
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::clear()
sp<Buffer> LayerBitmap::allocate()
{
// 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);
//}
Mutex::Autolock _l(mLock);
sp<Buffer> buffer(mBuffer);
const uint32_t w = mWidth;
const uint32_t h = mHeight;
if (buffer!=0 && (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;
}
status_t LayerBitmap::getInfo(surface_info_t* info) const
status_t LayerBitmap::free()
{
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);
mBuffer.clear();
mWidth = 0;
mHeight = 0;
return NO_ERROR;
}
status_t LayerBitmap::resize(uint32_t w, uint32_t h)
{
int err = setBits(w, h, mAlignment, pixelFormat(), SECURE_BITS);
return err;
}
size_t LayerBitmap::size() const
{
return mSize;
}
void LayerBitmap::getBitmapSurface(copybit_image_t* img) const
{
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();
}
// ---------------------------------------------------------------------------

View File

@@ -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 NativeBuffer;
class Buffer : public SurfaceBuffer
{
public:
enum {
DONT_CLEAR = 0x00000001,
GPU = 0x00000002,
SECURE = 0x00000004
};
// 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 {
// erase memory to ensure security when necessary
SECURE_BITS = 0x00000001
DONT_CLEAR = Buffer::DONT_CLEAR,
GPU = Buffer::GPU,
SECURE = Buffer::SECURE
};
LayerBitmap();
~LayerBitmap();
LayerBitmap();
~LayerBitmap();
status_t init(const sp<MemoryDealer>& allocator);
status_t init(surface_info_t* info,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
status_t setBits(uint32_t w, uint32_t h, uint32_t alignment,
PixelFormat format, uint32_t flags = 0);
void clear();
status_t getInfo(surface_info_t* info) const;
status_t resize(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;
status_t setSize(uint32_t w, uint32_t h);
sp<Buffer> allocate();
status_t free();
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

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
@@ -40,7 +38,7 @@ const char* const LayerBlur::typeID = "LayerBlur";
// ---------------------------------------------------------------------------
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i)
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
mRefreshCache(true), mCacheAge(0), mTextureName(-1U)
{
@@ -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);
}
}
}

View File

@@ -39,7 +39,7 @@ public:
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerBlur(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i);
const sp<Client>& client, int32_t i);
virtual ~LayerBlur();
virtual void onDraw(const Region& clip) const;

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
@@ -25,17 +23,16 @@
#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 <ui/FramebufferNativeWindow.h>
#include <hardware/copybit.h>
#include "LayerBuffer.h"
#include "SurfaceFlinger.h"
#include "VRamHeap.h"
#include "DisplayHardware/DisplayHardware.h"
#include "gralloc_priv.h" // needed for msm / copybit
namespace android {
@@ -47,7 +44,7 @@ const char* const LayerBuffer::typeID = "LayerBuffer";
// ---------------------------------------------------------------------------
LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i)
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i),
mNeedsBlending(false)
{
@@ -55,30 +52,24 @@ 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();
LayerBaseClient::onFirstRef();
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 +183,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)
status_t LayerBuffer::SurfaceBuffer::registerBuffers(
const ISurface::BufferHeap& buffers)
{
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)
{
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
// ============================================================================
@@ -276,20 +234,30 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
: mBufferHeap(buffers)
{
NativeBuffer& src(mNativeBuffer);
src.crop.l = 0;
src.crop.t = 0;
src.crop.r = buffers.w;
src.crop.b = buffers.h;
src.img.w = buffers.hor_stride ?: buffers.w;
src.img.h = buffers.ver_stride ?: buffers.h;
src.img.format = buffers.format;
src.img.offset = offset;
src.img.base = buffers.heap->base();
src.img.fd = buffers.heap->heapID();
src.img.w = buffers.hor_stride ?: buffers.w;
src.img.h = buffers.ver_stride ?: buffers.h;
src.img.format = buffers.format;
src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset);
// FIXME: gross hack, we should never access private_handle_t from here,
// but this is needed by msm drivers
private_handle_t* hnd = new private_handle_t(
buffers.heap->heapID(), buffers.heap->getSize(), 0);
hnd->offset = offset;
src.img.handle = hnd;
}
LayerBuffer::Buffer::~Buffer()
{
NativeBuffer& src(mNativeBuffer);
if (src.img.handle)
delete (private_handle_t*)src.img.handle;
}
// ============================================================================
@@ -323,8 +291,7 @@ bool LayerBuffer::Source::transformed() const {
LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
const ISurface::BufferHeap& buffers)
: Source(layer), mStatus(NO_ERROR),
mBufferSize(0), mTextureName(-1U)
: Source(layer), mStatus(NO_ERROR), mBufferSize(0)
{
if (buffers.heap == NULL) {
// this is allowed, but in this case, it is illegal to receive
@@ -363,13 +330,21 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
mLayer.forceVisibilityTransaction();
hw_module_t const* module;
mBlitEngine = NULL;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
copybit_open(module, &mBlitEngine);
}
}
LayerBuffer::BufferSource::~BufferSource()
{
if (mTextureName != -1U) {
LayerBase::deletedTextures.add(mTextureName);
if (mTexture.name != -1U) {
glDeleteTextures(1, &mTexture.name);
}
if (mBlitEngine) {
copybit_close(mBlitEngine);
}
}
@@ -427,19 +402,19 @@ bool LayerBuffer::BufferSource::transformed() const
void LayerBuffer::BufferSource::onDraw(const Region& clip) const
{
sp<Buffer> buffer(getBuffer());
if (UNLIKELY(buffer == 0)) {
sp<Buffer> ourBuffer(getBuffer());
if (UNLIKELY(ourBuffer == 0)) {
// nothing to do, we don't have a buffer
mLayer.clearWithOpenGL(clip);
return;
}
status_t err = NO_ERROR;
NativeBuffer src(buffer->getBuffer());
NativeBuffer src(ourBuffer->getBuffer());
const Rect& transformedBounds = mLayer.getTransformedBounds();
const int can_use_copybit = mLayer.canUseCopybit();
copybit_device_t* copybit = mBlitEngine;
if (can_use_copybit) {
if (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();
@@ -448,89 +423,108 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
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. */
#ifdef EGL_ANDROID_get_render_buffer
EGLDisplay dpy = eglGetCurrentDisplay();
EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
if (nb == 0) {
err = BAD_VALUE;
} else {
copybit_image_t dst;
dst.w = nb->width;
dst.h = nb->height;
dst.format = nb->format;
dst.base = NULL; // unused by copybit on msm7k
dst.handle = (native_handle_t *)nb->handle;
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);
/* 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. */
float xscale = 1.0f;
if (src_width > W*min) xscale = 1.0f / min;
else if (src_width*mag < W) xscale = mag;
const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
float yscale = 1.0f;
if (src_height > H*min) yscale = 1.0f / min;
else if (src_height*mag < H) yscale = mag;
float xscale = 1.0f;
if (src_width > W*min) xscale = 1.0f / min;
else if (src_width*mag < W) xscale = 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);
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)) {
const int tmp_w = floorf(src_width * xscale);
const int tmp_h = floorf(src_height * yscale);
if (mTempBitmap==0 ||
mTempBitmap->getWidth() < tmp_w ||
mTempBitmap->getHeight() < tmp_h) {
mTempBitmap.clear();
mTempBitmap = new android::Buffer(tmp_w, tmp_h, src.img.format);
err = mTempBitmap->initCheck();
}
if (LIKELY(err == NO_ERROR)) {
NativeBuffer tmp;
tmp.img.w = tmp_w;
tmp.img.h = tmp_h;
tmp.img.format = src.img.format;
tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
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 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);
const Rect& transformedBounds = mLayer.getTransformedBounds();
const copybit_rect_t& drect =
reinterpret_cast<const copybit_rect_t&>(transformedBounds);
const State& s(mLayer.drawingState());
region_iterator it(clip);
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;
// 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();
}
}
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);
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));
err = copybit->stretch(copybit,
&dst, &src.img, &drect, &src.crop, &it);
if (err != NO_ERROR) {
LOGE("copybit failed (%s)", strerror(err));
}
}
}
if (!can_use_copybit || err) {
if (UNLIKELY(mTextureName == -1LU)) {
mTextureName = mLayer.createTexture();
#endif
if (!copybit || err)
{
// OpenGL fall-back
if (UNLIKELY(mTexture.name == -1LU)) {
mTexture.name = mLayer.createTexture();
}
GLuint w = 0;
GLuint h = 0;
@@ -541,10 +535,11 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
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);
t.data = (GGLubyte*)src.img.base;
const Region dirty(Rect(t.width, t.height));
mLayer.loadTexture(dirty, mTextureName, t, w, h);
mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
mLayer.loadTexture(&mTexture, mTexture.name, dirty, t);
mTexture.transform = mBufferHeap.transform;
mLayer.drawWithOpenGL(clip, mTexture);
}
}

View File

@@ -22,16 +22,16 @@
#include <binder/IMemory.h>
#include <private/ui/LayerState.h>
#include <EGL/eglnatives.h>
#include "LayerBase.h"
#include "LayerBitmap.h"
struct copybit_device_t;
namespace android {
// ---------------------------------------------------------------------------
class MemoryDealer;
class Region;
class OverlayRef;
@@ -51,7 +51,6 @@ class LayerBuffer : public LayerBaseClient
LayerBuffer& mLayer;
};
public:
static const uint32_t typeInfo;
static const char* const typeID;
@@ -59,12 +58,14 @@ public:
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i);
const sp<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);
@@ -121,14 +122,14 @@ private:
virtual void unregisterBuffers();
virtual bool transformed() const;
private:
mutable Mutex mLock;
sp<Buffer> mBuffer;
status_t mStatus;
ISurface::BufferHeap mBufferHeap;
size_t mBufferSize;
mutable sp<MemoryDealer> mTemporaryDealer;
mutable LayerBitmap mTempBitmap;
mutable GLuint mTextureName;
mutable Mutex mLock;
sp<Buffer> mBuffer;
status_t mStatus;
ISurface::BufferHeap mBufferHeap;
size_t mBufferSize;
mutable sp<android::Buffer> mTempBitmap;
mutable LayerBase::Texture mTexture;
copybit_device_t* mBlitEngine;
};
class OverlaySource : public Source {
@@ -179,34 +180,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;
};
// ---------------------------------------------------------------------------

View File

@@ -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,27 +30,74 @@ namespace android {
const uint32_t LayerDim::typeInfo = LayerBaseClient::typeInfo | 0x10;
const char* const LayerDim::typeID = "LayerDim";
sp<MemoryDealer> LayerDim::mDimmerDealer;
LayerBitmap LayerDim::mDimmerBitmap;
bool LayerDim::sUseTexture;
GLuint LayerDim::sTexId;
EGLImageKHR LayerDim::sImage;
int32_t LayerDim::sWidth;
int32_t LayerDim::sHeight;
// ---------------------------------------------------------------------------
LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i)
: LayerBaseClient(flinger, display, client, i)
const sp<Client>& client, int32_t i)
: LayerBaseClient(flinger, display, client, i)
{
}
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();
sTexId = -1;
sImage = EGL_NO_IMAGE_KHR;
sWidth = w;
sHeight = h;
sUseTexture = false;
#ifdef DIM_WITH_TEXTURE
#warning "using a texture to implement LayerDim"
/* On some h/w like msm7K, it is faster to use a texture because the
* software renderer will defer to copybit, for this to work we need to
* use an EGLImage texture so copybit can actually make use of it.
* This burns a full-screen worth of graphic memory.
*/
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
uint32_t flags = hw.getFlags();
if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
// TODO: api to pass the usage flags
sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565);
android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
glGenTextures(1, &sTexId);
glBindTexture(GL_TEXTURE_2D, sTexId);
EGLDisplay dpy = eglGetCurrentDisplay();
sImage = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)clientBuf, 0);
if (sImage == EGL_NO_IMAGE_KHR) {
LOGE("eglCreateImageKHR() failed. err=0x%4x", eglGetError());
return;
}
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)sImage);
GLint error = glGetError();
if (error != GL_NO_ERROR) {
eglDestroyImageKHR(dpy, sImage);
LOGE("glEGLImageTargetTexture2DOES() failed. err=0x%4x", error);
return;
}
// initialize the texture with zeros
GGLSurface t;
buffer->lock(&t, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN);
memset(t.data, 0, t.stride * t.height * 2);
buffer->unlock();
sUseTexture = true;
}
#endif
}
LayerDim::~LayerDim()
@@ -63,49 +107,56 @@ LayerDim::~LayerDim()
void LayerDim::onDraw(const Region& clip) const
{
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);
const GGLfixed alpha = (s.alpha << 16)/255;
const uint32_t fbHeight = hw.getHeight();
glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4x(0, 0, 0, alpha);
#ifdef DIM_WITH_TEXTURE
if (sUseTexture) {
glBindTexture(GL_TEXTURE_2D, sTexId);
glEnable(GL_TEXTURE_2D);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
const GLshort texCoords[4][2] = {
{ 0, 0 },
{ 0, 1 },
{ 1, 1 },
{ 1, 0 }
};
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_SHORT, 0, texCoords);
} else
#endif
{
glDisable(GL_TEXTURE_2D);
}
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);
}
GLshort w = sWidth;
GLshort h = sHeight;
const GLshort vertices[4][2] = {
{ 0, 0 },
{ 0, h },
{ w, h },
{ w, 0 }
};
glVertexPointer(2, GL_SHORT, 0, vertices);
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);
}
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// ---------------------------------------------------------------------------

View File

@@ -20,6 +20,9 @@
#include <stdint.h>
#include <sys/types.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "LayerBase.h"
#include "LayerBitmap.h"
@@ -29,6 +32,11 @@ namespace android {
class LayerDim : public LayerBaseClient
{
static bool sUseTexture;
static GLuint sTexId;
static EGLImageKHR sImage;
static int32_t sWidth;
static int32_t sHeight;
public:
static const uint32_t typeInfo;
static const char* const typeID;
@@ -36,7 +44,7 @@ public:
virtual uint32_t getTypeInfo() const { return typeInfo; }
LayerDim(SurfaceFlinger* flinger, DisplayID display,
Client* client, int32_t i);
const sp<Client>& client, int32_t i);
virtual ~LayerDim();
virtual void onDraw(const Region& clip) const;
@@ -44,10 +52,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;
};
// ---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,10 @@
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <binder/MemoryDealer.h>
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/Permission.h>
#include <ui/PixelFormat.h>
#include <ui/ISurfaceComposer.h>
@@ -33,13 +36,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 +54,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;
@@ -66,7 +64,7 @@ typedef int32_t ClientID;
// ---------------------------------------------------------------------------
class Client
class Client : public RefBase
{
public:
Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
@@ -74,17 +72,19 @@ 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; }
const sp<IMemory>& controlBlockMemory() const { return mCblkMemory; }
sp<LayerBaseClient> getLayerUser(int32_t i) const;
void dump(const char* what);
const sp<SurfaceHeapManager>& getSurfaceHeapManager() const;
const Vector< wp<LayerBaseClient> >& getLayers() const {
return mLayers;
}
const sp<IMemoryHeap>& getControlBlockMemory() const {
return mCblkHeap;
}
// pointer to this client's control block
per_client_cblk_t* ctrlblk;
@@ -92,17 +92,14 @@ public:
private:
int getClientPid() const { return mPid; }
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<IMemoryHeap> mCblkHeap;
sp<SurfaceFlinger> mFlinger;
};
// ---------------------------------------------------------------------------
@@ -125,6 +122,8 @@ public:
const DisplayHardware& displayHardware() const;
const Transform& transform() const;
EGLDisplay getEGLDisplay() const;
private:
GraphicPlane(const GraphicPlane&);
GraphicPlane operator = (const GraphicPlane&);
@@ -160,7 +159,7 @@ public:
// ISurfaceComposer interface
virtual sp<ISurfaceFlingerClient> createConnection();
virtual sp<IMemory> getCblk() const;
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
virtual void openGlobalTransaction();
virtual void closeGlobalTransaction();
@@ -168,28 +167,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;
@@ -198,26 +185,33 @@ private:
friend class LayerBaseClient;
friend class Layer;
friend class LayerBlur;
friend class LayerDim;
sp<ISurface> createSurface(ClientID client, int pid,
ISurfaceFlingerClient::surface_data_t* params,
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(
const sp<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(
const sp<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(
const sp<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(
const sp<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 +219,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 +241,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();
@@ -279,6 +254,9 @@ private:
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(
uint32_t transactionFlags,
Vector< sp<LayerBase> >& ditchedLayers);
void computeVisibleRegions(
LayerVector& currentLayers,
@@ -289,8 +267,7 @@ private:
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
void handleRepaint();
void handleDebugCpu();
void scheduleBroadcast(Client* client);
void scheduleBroadcast(const sp<Client>& client);
void executeScheduledBroadcasts();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
@@ -298,10 +275,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 +300,11 @@ private:
void debugShowFPS() const;
void drawWormhole() const;
mutable MessageQueue mEventQueue;
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState;
@@ -330,53 +312,43 @@ private:
volatile int32_t mTransactionFlags;
volatile int32_t mTransactionCount;
Condition mTransactionCV;
// protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
DefaultKeyedVector<ClientID, Client*> mClientsMap;
DefaultKeyedVector<SurfaceID, LayerBaseClient*> mLayerMap;
DefaultKeyedVector<ClientID, sp<Client> > mClientsMap;
DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap;
GraphicPlane mGraphicPlanes[1];
SortedVector<LayerBase*> mRemovedLayers;
Vector<Client*> mDisconnectedClients;
bool mLayersRemoved;
Vector< sp<Client> > mDisconnectedClients;
// constant members (no synchronization needed for access)
sp<MemoryDealer> mServerHeap;
sp<IMemory> mServerCblkMemory;
sp<IMemoryHeap> mServerHeap;
surface_flinger_cblk_t* mServerCblk;
sp<SurfaceHeapManager> mSurfaceHeapManager;
sp<GPUHardwareInterface> mGPU;
GLuint mWormholeTexName;
nsecs_t mBootTime;
Permission mHardwareTest;
Permission mAccessSurfaceFlinger;
Permission mDump;
// Can only accessed from the main thread, these members
// don't need synchronization
Region mDirtyRegion;
Region mInvalidRegion;
Region mWormholeRegion;
Client* mLastScheduledBroadcast;
SortedVector<Client*> mScheduledBroadcasts;
wp<Client> mLastScheduledBroadcast;
SortedVector< wp<Client> > mScheduledBroadcasts;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
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 {
@@ -409,11 +381,11 @@ class BClient : public BnSurfaceFlingerClient
{
public:
BClient(SurfaceFlinger *flinger, ClientID cid,
const sp<IMemory>& cblk);
const sp<IMemoryHeap>& cblk);
~BClient();
// ISurfaceFlingerClient interface
virtual void getControlBlocks(sp<IMemory>* ctrl) const;
virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
surface_data_t* params, int pid,
@@ -426,7 +398,7 @@ public:
private:
ClientID mId;
SurfaceFlinger* mFlinger;
sp<IMemory> mCblk;
sp<IMemoryHeap> mCblk;
};
// ---------------------------------------------------------------------------

View File

@@ -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));
}
}

View File

@@ -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()));

View File

@@ -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;
if (alphaIn > 0.0f) {
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 (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);
}
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -72,8 +72,7 @@ private:
bool finished();
sp<SurfaceFlinger> mFlinger;
sp<MemoryDealer> mTemporaryDealer;
LayerOrientationAnimBase* mLayerOrientationAnim;
sp< LayerOrientationAnimBase > mLayerOrientationAnim;
int mState;
uint32_t mType;
};

View File

@@ -14,8 +14,6 @@
* limitations under the License.
*/
#define LOG_TAG "SurfaceFlinger"
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
@@ -30,12 +28,10 @@
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/MemoryDealer.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapPmem.h>
#include <binder/MemoryHeapBase.h>
#include <EGL/eglnatives.h>
#include <utils/MemoryDealer.h>
#include <utils/MemoryBase.h>
#include <utils/MemoryHeapPmem.h>
#include <utils/MemoryHeapBase.h>
#include "GPUHardware/GPUHardware.h"
#include "SurfaceFlinger.h"
@@ -55,7 +51,7 @@ namespace android {
* (PMEM is used for 2D acceleration)
* 8 MB of address space per client should be enough.
*/
static const int PMEM_SIZE = int(16 * 1024 * 1024);
static const int PMEM_SIZE = int(8 * 1024 * 1024);
int SurfaceHeapManager::global_pmem_heap = 0;
@@ -79,11 +75,7 @@ void SurfaceHeapManager::onFirstRef()
mPMemHeap = new PMemHeap(device, PMEM_SIZE);
if (mPMemHeap->base() == MAP_FAILED) {
mPMemHeap.clear();
mPMemHeap = new PMemHeap(device, PMEM_SIZE/2);
if (mPMemHeap->base() == MAP_FAILED) {
mPMemHeap.clear();
global_pmem_heap = 0;
}
global_pmem_heap = 0;
}
}
}
@@ -104,7 +96,7 @@ sp<MemoryDealer> SurfaceHeapManager::createHeap(
}
}
if ((flags & ISurfaceComposer::eGPU) && (mFlinger->getGPU() != 0)) {
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

View File

@@ -19,7 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <binder/MemoryDealer.h>
#include <utils/MemoryDealer.h>
namespace android {

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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 \
@@ -27,7 +27,6 @@ LOCAL_SRC_FILES:= \
SurfaceFlingerSynchro.cpp
LOCAL_SHARED_LIBRARIES := \
libcorecg \
libcutils \
libutils \
libbinder \

80
libs/ui/BufferMapper.cpp Normal file
View File

@@ -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

View File

@@ -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
// ----------------------------------------------------------------------------

View File

@@ -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
// ----------------------------------------------------------------------------

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -54,12 +54,12 @@ public:
return interface_cast<ISurfaceFlingerClient>(reply.readStrongBinder());
}
virtual sp<IMemory> getCblk() const
virtual sp<IMemoryHeap> getCblk() const
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_CBLK, data, &reply);
return interface_cast<IMemory>(reply.readStrongBinder());
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
}
virtual void openGlobalTransaction()
@@ -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);
}
}
};

View File

@@ -64,12 +64,12 @@ public:
{
}
virtual void getControlBlocks(sp<IMemory>* ctl) const
virtual sp<IMemoryHeap> getControlBlock() const
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceFlingerClient::getInterfaceDescriptor());
remote()->transact(GET_CBLK, data, &reply);
*ctl = interface_cast<IMemory>(reply.readStrongBinder());
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
}
virtual sp<ISurface> createSurface( surface_data_t* params,
@@ -126,8 +126,7 @@ status_t BnSurfaceFlingerClient::onTransact(
switch(code) {
case GET_CBLK: {
CHECK_INTERFACE(ISurfaceFlingerClient, data, reply);
sp<IMemory> ctl;
getControlBlocks(&ctl);
sp<IMemoryHeap> ctl(getControlBlock());
reply->writeStrongBinder(ctl->asBinder());
return NO_ERROR;
} break;
@@ -192,8 +191,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 +198,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;
}

View File

@@ -16,295 +16,659 @@
#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)
: mBounds(rhs.mBounds), mStorage(rhs.mStorage)
{
}
Region::Region(const SkRegion& rhs)
: mRegion(rhs)
Region::Region(const Rect& rhs)
: mBounds(rhs)
{
}
Region::Region(const Parcel& parcel)
{
status_t err = read(parcel);
LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
}
Region::Region(const void* buffer)
{
status_t err = read(buffer);
LOGE_IF(err<0, "error %s reading Region from parcel", strerror(err));
}
Region::~Region()
{
}
Region::Region(const Rect& rhs)
{
set(rhs);
}
Region::Region(const Parcel& parcel)
{
read(parcel);
}
Region::Region(const void* buffer)
{
read(buffer);
}
Region& Region::operator = (const Region& rhs)
{
mRegion = rhs.mRegion;
#if VALIDATE_REGIONS
validate(rhs, "operator=");
#endif
mBounds = rhs.mBounds;
mStorage = rhs.mStorage;
return *this;
}
const SkRegion& Region::toSkRegion() const
Region& Region::makeBoundsSelf()
{
return mRegion;
}
Rect Region::bounds() const
{
const SkIRect& b(mRegion.getBounds());
return Rect(b.fLeft, b.fTop, b.fRight, b.fBottom);
mStorage.clear();
return *this;
}
void Region::clear()
{
mRegion.setEmpty();
mBounds.clear();
mStorage.clear();
}
void Region::set(const Rect& r)
{
SkIRect ir;
ir.set(r.left, r.top, r.right, r.bottom);
mRegion.setRect(ir);
mBounds = r;
mStorage.clear();
}
void Region::set(uint32_t w, uint32_t h)
{
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 {
// ----------------------------------------------------------------------------
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::kUnion_Op);
boolean_operation(op, result, *this, rhs);
return result;
}
Region Region::intersect(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::kIntersect_Op);
boolean_operation(op, result, *this, rhs);
return result;
}
Region Region::subtract(const Region& rhs) const {
const Region Region::translate(int x, int y) const {
Region result;
result.mRegion.op(mRegion, rhs.mRegion, SkRegion::kDifference_Op);
return result;
}
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 {
Region result;
SkRegion r(rhs.mRegion);
r.translate(dx, dy);
result.mRegion.op(mRegion, r, SkRegion::kUnion_Op);
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);
return result;
const Region Region::merge(const Region& rhs, int dx, int dy) const {
return operation(rhs, dx, dy, op_or);
}
Region Region::subtract(const Region& rhs, int dx, int dy) const {
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::kDifference_Op);
boolean_operation(op, result, *this, rhs, dx, dy);
return result;
}
// ----------------------------------------------------------------------------
Region::iterator::iterator(const Region& r)
: mIt(r.mRegion)
// 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;
}
int Region::iterator::iterate(Rect* rect)
void Region::boolean_operation(int op, Region& dst,
const Region& lhs,
const Region& rhs, int dx, int dy)
{
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;
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
}
void Region::boolean_operation(int op, Region& dst,
const Region& lhs, const Region& rhs)
{
boolean_operation(op, dst, lhs, rhs, 0, 0);
}
void Region::boolean_operation(int op, Region& dst,
const Region& lhs, const Rect& rhs)
{
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();
}
size_t Region::rects(Vector<Rect>& rectList) const
// ----------------------------------------------------------------------------
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::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++;
}
}

View File

@@ -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,
SurfaceBuffer::SurfaceBuffer()
: BASE(), mOwner(false), mBufferMapper(BufferMapper::get())
{
width =
height =
stride =
format =
usage = 0;
handle = NULL;
}
SurfaceBuffer::SurfaceBuffer(const Parcel& data)
: BASE(), mOwner(true), mBufferMapper(BufferMapper::get())
{
// 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();
}
SurfaceBuffer::~SurfaceBuffer()
{
if (handle && mOwner) {
native_handle_close(handle);
native_handle_delete(const_cast<native_handle*>(handle));
}
}
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 SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
{
status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
return res;
}
status_t SurfaceBuffer::unlock()
{
status_t res = getBufferMapper().unlock(handle);
return res;
}
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;
}
// ----------------------------------------------------------------------
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();
}
// ============================================================================
// 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,
bool owner)
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), mOwner(owner)
mFormat(format), mFlags(flags)
{
mSwapRectangle.makeInvalid();
mSurfaceHeapBase[0] = 0;
mSurfaceHeapBase[1] = 0;
mHeap[0] = data.heap[0];
mHeap[1] = data.heap[1];
}
SurfaceControl::~SurfaceControl()
{
destroy();
}
Surface::Surface(Surface const* rhs)
: mOwner(false)
void SurfaceControl::destroy()
{
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();
}
Surface::~Surface()
{
if (mOwner && mToken>=0 && mClient!=0) {
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();
mHeap[0].clear();
mHeap[1].clear();
IPCThreadState::self()->flushCommands();
}
sp<Surface> Surface::dup() const
void SurfaceControl::clear()
{
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);
// 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();
}
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 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 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 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 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 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 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 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 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);
}
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);
}
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);
}
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);
}
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);
}
status_t SurfaceControl::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;
}
return const_cast<Surface*>(r);
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::nextBuffer(SurfaceInfo* info) {
return mClient->nextBuffer(this, info);
}
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
return Surface::lock(info, NULL, blocking);
}
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 Surface::unlockAndPost() {
if (heapBase(0) == 0) return INVALID_OPERATION;
if (heapBase(1) == 0) return INVALID_OPERATION;
return mClient->unlockAndPostSurface(this);
}
status_t Surface::unlock() {
if (heapBase(0) == 0) return INVALID_OPERATION;
if (heapBase(1) == 0) return INVALID_OPERATION;
return mClient->unlockSurface(this);
}
status_t Surface::setLayer(int32_t layer) {
return mClient->setLayer(this, layer);
}
status_t Surface::setPosition(int32_t x, int32_t y) {
return mClient->setPosition(this, x, y);
}
status_t Surface::setSize(uint32_t w, uint32_t h) {
return mClient->setSize(this, w, h);
}
status_t Surface::hide() {
return mClient->hide(this);
}
status_t Surface::show(int32_t layer) {
return mClient->show(this, layer);
}
status_t Surface::freeze() {
return mClient->freeze(this);
}
status_t Surface::unfreeze() {
return mClient->unfreeze(this);
}
status_t Surface::setFlags(uint32_t flags, uint32_t mask) {
return mClient->setFlags(this, flags, mask);
}
status_t Surface::setTransparentRegionHint(const Region& transparent) {
return mClient->setTransparentRegionHint(this, transparent);
}
status_t Surface::setAlpha(float alpha) {
return mClient->setAlpha(this, alpha);
}
status_t Surface::setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
return mClient->setMatrix(this, dsdx, dtdx, dsdy, dtdy);
}
status_t Surface::setFreezeTint(uint32_t tint) {
return mClient->setFreezeTint(this, tint);
}
Region Surface::dirtyRegion() const {
return mDirtyRegion;
}
void Surface::setDirtyRegion(const Region& region) const {
mDirtyRegion = region;
}
const Rect& Surface::swapRectangle() const {
return mSwapRectangle;
}
void Surface::setSwapRectangle(const Rect& r) {
mSwapRectangle = r;
}
sp<Surface> Surface::readFromParcel(Parcel* parcel)
status_t SurfaceControl::writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel)
{
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);
}
status_t Surface::writeToParcel(const sp<Surface>& surface, 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)
{
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());
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)
{
// 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 heapBase;
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 err;
}
}; // namespace android

View File

@@ -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
@@ -65,7 +59,7 @@ static Mutex gLock;
static sp<ISurfaceComposer> gSurfaceManager;
static DefaultKeyedVector< sp<IBinder>, sp<SurfaceComposerClient> > gActiveConnections;
static SortedVector<sp<SurfaceComposerClient> > gOpenTransactions;
static sp<IMemory> gServerCblkMemory;
static sp<IMemoryHeap> gServerCblkMemory;
static volatile surface_flinger_cblk_t* gServerCblk;
const sp<ISurfaceComposer>& _get_surface_manager()
@@ -100,7 +94,7 @@ static volatile surface_flinger_cblk_t const * get_cblk()
if (gServerCblk == 0) {
gServerCblkMemory = sm->getCblk();
LOGE_IF(gServerCblkMemory==0, "Can't get server control block");
gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->pointer();
gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->getBase();
LOGE_IF(gServerCblk==0, "Can't get server control block address");
}
}
@@ -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;
}
@@ -360,9 +313,9 @@ void SurfaceComposerClient::_init(
return;
}
mClient->getControlBlocks(&mControlMemory);
mControlMemory = mClient->getControlBlock();
mSignalServer = new SurfaceFlingerSynchro(sm);
mControl = static_cast<per_client_cblk_t *>(mControlMemory->pointer());
mControl = static_cast<per_client_cblk_t *>(mControlMemory->getBase());
}
SurfaceComposerClient::~SurfaceComposerClient()
@@ -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;
@@ -437,9 +364,8 @@ void SurfaceComposerClient::dispose()
{
// this can be called more than once.
sp<IMemory> controlMemory;
sp<IMemoryHeap> 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;

View File

@@ -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

16
libs/ui/tests/Android.mk Normal file
View File

@@ -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)

62
libs/ui/tests/region.cpp Normal file
View File

@@ -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;
}

View File

@@ -27,9 +27,14 @@
#include <unistd.h>
#include <string.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <utils/misc.h>
#include <android_runtime/ActivityManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h>

View File

@@ -131,6 +131,30 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL
/* Interfaces defined by EGL_KHR_image above */
#endif
#ifndef EGL_ANDROID_image_native_buffer
#define EGL_ANDROID_image_native_buffer 1
struct android_native_buffer_t;
#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */
#endif
#ifndef EGL_ANDROID_get_render_buffer
#define EGL_ANDROID_get_render_buffer 1
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLClientBuffer EGLAPIENTRY eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw);
#endif
typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETRENDERBUFFERANDROIDPROC) (EGLDisplay dpy, EGLSurface draw);
#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

Some files were not shown because too many files have changed in this diff Show More