Merge commit 'goog/master_gl' into merge_master_gl
This commit is contained in:
@@ -12,6 +12,8 @@ ifeq ($(TARGET_SIMULATOR),true)
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libutils \
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;");
|
||||
|
||||
|
||||
@@ -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
0
core/res/res/drawable/stat_sys_signal_flightmode.png
Normal file → Executable file
|
Before Width: | Height: | Size: 898 B After Width: | Height: | Size: 898 B |
@@ -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);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
68
include/binder/Permission.h
Normal file
68
include/binder/Permission.h
Normal 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 */
|
||||
@@ -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() {
|
||||
|
||||
279
include/private/ui/RegionHelper.h
Normal file
279
include/private/ui/RegionHelper.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
77
include/private/ui/SurfaceBuffer.h
Normal file
77
include/private/ui/SurfaceBuffer.h
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
62
include/private/ui/android_natives_priv.h
Normal file
62
include/private/ui/android_natives_priv.h
Normal 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
64
include/ui/BufferMapper.h
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
85
include/ui/FramebufferNativeWindow.h
Normal file
85
include/ui/FramebufferNativeWindow.h
Normal 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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
210
include/ui/egl/android_natives.h
Normal file
210
include/ui/egl/android_natives.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
69
include/utils/Singleton.h
Normal 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
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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 }; };
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -29,6 +29,7 @@ LOCAL_SRC_FILES:= \
|
||||
MemoryHeapBase.cpp \
|
||||
MemoryHeapPmem.cpp \
|
||||
Parcel.cpp \
|
||||
Permission.cpp \
|
||||
ProcessState.cpp \
|
||||
Static.cpp
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
88
libs/binder/Permission.cpp
Normal file
88
libs/binder/Permission.cpp
Normal 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
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <math.h>
|
||||
#include <utils/misc.h>
|
||||
|
||||
#include <ui/EGLNativeWindowSurface.h>
|
||||
#include <ui/Surface.h>
|
||||
|
||||
#include <core/SkBitmap.h>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
118
libs/surfaceflinger/BufferAllocator.cpp
Normal file
118
libs/surfaceflinger/BufferAllocator.cpp
Normal 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
|
||||
96
libs/surfaceflinger/BufferAllocator.h
Normal file
96
libs/surfaceflinger/BufferAllocator.h
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "SurfaceFlinger"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
188
libs/surfaceflinger/MessageQueue.cpp
Normal file
188
libs/surfaceflinger/MessageQueue.cpp
Normal 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
|
||||
127
libs/surfaceflinger/MessageQueue.h
Normal file
127
libs/surfaceflinger/MessageQueue.h
Normal 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
@@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@ private:
|
||||
bool finished();
|
||||
|
||||
sp<SurfaceFlinger> mFlinger;
|
||||
sp<MemoryDealer> mTemporaryDealer;
|
||||
LayerOrientationAnimBase* mLayerOrientationAnim;
|
||||
sp< LayerOrientationAnimBase > mLayerOrientationAnim;
|
||||
int mState;
|
||||
uint32_t mType;
|
||||
};
|
||||
@@ -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
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <binder/MemoryDealer.h>
|
||||
#include <utils/MemoryDealer.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
16
libs/surfaceflinger/tests/resize/Android.mk
Normal file
16
libs/surfaceflinger/tests/resize/Android.mk
Normal 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)
|
||||
60
libs/surfaceflinger/tests/resize/resize.cpp
Normal file
60
libs/surfaceflinger/tests/resize/resize.cpp
Normal 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;
|
||||
}
|
||||
@@ -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
80
libs/ui/BufferMapper.cpp
Normal 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
|
||||
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
210
libs/ui/FramebufferNativeWindow.cpp
Normal file
210
libs/ui/FramebufferNativeWindow.cpp
Normal 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
16
libs/ui/tests/Android.mk
Normal 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
62
libs/ui/tests/region.cpp
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user