implement display viewport and frame
note: viewport clipping is not implemented yet
Change-Id: I7fde7c4de075d409d95c48bb20ba8ee017f6f00a
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 16e5547..cf781d3 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -38,6 +38,7 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
+#include "clz.h"
#include "DisplayDevice.h"
#include "GLExtensions.h"
#include "SurfaceFlinger.h"
@@ -84,8 +85,8 @@
mPageFlipCount(),
mSecureLayerVisible(false),
mScreenAcquired(false),
- mOrientation(),
- mLayerStack(0)
+ mLayerStack(0),
+ mOrientation()
{
init(config);
}
@@ -139,6 +140,8 @@
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
+ mViewport.makeInvalid();
+ mFrame.makeInvalid();
// external displays are always considered enabled
mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES);
@@ -192,12 +195,23 @@
}
}
-void DisplayDevice::makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx) {
+EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy,
+ const sp<const DisplayDevice>& hw, EGLContext ctx) {
+ EGLBoolean result = EGL_TRUE;
EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
if (sur != hw->mSurface) {
- EGLDisplay dpy = eglGetCurrentDisplay();
- eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
+ result = eglMakeCurrent(dpy, hw->mSurface, hw->mSurface, ctx);
+ if (result == EGL_TRUE) {
+ GLsizei w = hw->mDisplayWidth;
+ GLsizei h = hw->mDisplayHeight;
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // put the origin in the left-bottom corner
+ glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
+ }
}
+ return result;
}
// ----------------------------------------------------------------------------
@@ -223,10 +237,10 @@
Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
Region dirty;
- const Transform& planeTransform(mGlobalTransform);
if (repaintEverything) {
dirty.set(getBounds());
} else {
+ const Transform& planeTransform(mGlobalTransform);
dirty = planeTransform.transform(this->dirtyRegion);
dirty.andSelf(getBounds());
}
@@ -284,18 +298,73 @@
return NO_ERROR;
}
-status_t DisplayDevice::setOrientation(int orientation) {
+void DisplayDevice::setOrientation(int orientation) {
+ mOrientation = orientation;
+ updateGeometryTransform();
+}
+
+void DisplayDevice::setViewport(const Rect& viewport) {
+ if (viewport.isValid()) {
+ mViewport = viewport;
+ updateGeometryTransform();
+ }
+}
+
+void DisplayDevice::setFrame(const Rect& frame) {
+ if (frame.isValid()) {
+ mFrame = frame;
+ updateGeometryTransform();
+ }
+}
+
+void DisplayDevice::updateGeometryTransform() {
int w = mDisplayWidth;
int h = mDisplayHeight;
+ Transform R, S;
+ if (DisplayDevice::orientationToTransfrom(
+ mOrientation, w, h, &R) == NO_ERROR) {
+ dirtyRegion.set(bounds());
- DisplayDevice::orientationToTransfrom(
- orientation, w, h, &mGlobalTransform);
- if (orientation & DisplayState::eOrientationSwapMask) {
- int tmp = w;
- w = h;
- h = tmp;
+ Rect viewport(mViewport);
+ Rect frame(mFrame);
+
+ if (!frame.isValid()) {
+ // the destination frame can be invalid if it has never been set,
+ // in that case we assume the whole display frame.
+ frame = Rect(w, h);
+ }
+
+ if (viewport.isEmpty()) {
+ // viewport can be invalid if it has never been set, in that case
+ // we assume the whole display size.
+ // it's also invalid to have an empty viewport, so we handle that
+ // case in the same way.
+ viewport = Rect(w, h);
+ if (R.getOrientation() & Transform::ROT_90) {
+ // viewport is always specified in the logical orientation
+ // of the display (ie: post-rotation).
+ swap(viewport.right, viewport.bottom);
+ }
+ }
+
+ float src_width = viewport.width();
+ float src_height = viewport.height();
+ float dst_width = frame.width();
+ float dst_height = frame.height();
+ if (src_width != src_height || dst_width != dst_height) {
+ float sx = dst_width / src_width;
+ float sy = dst_height / src_height;
+ S.set(sx, 0, 0, sy);
+ }
+ float src_x = viewport.left;
+ float src_y = viewport.top;
+ float dst_x = frame.left;
+ float dst_y = frame.top;
+ float tx = dst_x - src_x;
+ float ty = dst_y - src_y;
+ S.set(tx, ty);
+
+ // rotate first, followed by scaling
+ mGlobalTransform = S * R;
}
- mOrientation = orientation;
- dirtyRegion.set(bounds());
- return NO_ERROR;
}