implement display viewport and frame

note: viewport clipping is not implemented yet

Change-Id: I7fde7c4de075d409d95c48bb20ba8ee017f6f00a
This commit is contained in:
Mathias Agopian 2012-09-04 15:05:38 -07:00
parent 493db47929
commit da8d0a5c0c
4 changed files with 125 additions and 47 deletions

View File

@ -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 @@ DisplayDevice::DisplayDevice(
mPageFlipCount(),
mSecureLayerVisible(false),
mScreenAcquired(false),
mOrientation(),
mLayerStack(0)
mLayerStack(0),
mOrientation()
{
init(config);
}
@ -139,6 +140,8 @@ void DisplayDevice::init(EGLConfig config)
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::dump(String8& res) const
}
}
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 @@ bool DisplayDevice::getSecureLayerVisible() const {
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 @@ status_t DisplayDevice::orientationToTransfrom(
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;
}

View File

@ -93,11 +93,16 @@ public:
bool getSecureLayerVisible() const;
Region getDirtyRegion(bool repaintEverything) const;
status_t setOrientation(int orientation);
void setLayerStack(uint32_t stack);
void setOrientation(int orientation);
void setViewport(const Rect& viewport);
void setFrame(const Rect& frame);
int getOrientation() const { return mOrientation; }
const Transform& getTransform() const { return mGlobalTransform; }
const Rect& getViewport() const { return mViewport; }
const Rect& getFrame() const { return mFrame; }
uint32_t getLayerStack() const { return mLayerStack; }
int32_t getDisplayType() const { return mType; }
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
@ -110,7 +115,8 @@ public:
}
inline Rect bounds() const { return getBounds(); }
static void makeCurrent(const sp<const DisplayDevice>& hw, EGLContext ctx);
static EGLBoolean makeCurrent(EGLDisplay dpy,
const sp<const DisplayDevice>& hw, EGLContext ctx);
/* ------------------------------------------------------------------------
* blank / unplank management
@ -170,11 +176,16 @@ private:
/*
* Transaction state
*/
static status_t orientationToTransfrom(int orientation, int w, int h,
Transform* tr);
Transform mGlobalTransform;
int mOrientation;
static status_t orientationToTransfrom(int orientation,
int w, int h, Transform* tr);
void updateGeometryTransform();
uint32_t mLayerStack;
int mOrientation;
Rect mViewport;
Rect mFrame;
Transform mGlobalTransform;
};
}; // namespace android

View File

@ -297,8 +297,8 @@ EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config)
return ctxt;
}
void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
EGLBoolean result = eglMakeCurrent(display, surface, surface, mEGLContext);
void SurfaceFlinger::initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw) {
EGLBoolean result = DisplayDevice::makeCurrent(display, hw, mEGLContext);
if (!result) {
ALOGE("Couldn't create a working GLES context. check logs. exiting...");
exit(0);
@ -314,10 +314,6 @@ void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
eglQueryString(display, EGL_VERSION),
eglQueryString(display, EGL_EXTENSIONS));
EGLint w, h;
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@ -344,12 +340,6 @@ void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
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
// print some debugging info
EGLint r,g,b,a;
eglGetConfigAttrib(display, mEGLConfig, EGL_RED_SIZE, &r);
@ -412,8 +402,7 @@ status_t SurfaceFlinger::readyToRun()
mDisplays.add(mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY], hw);
// initialize OpenGL ES
EGLSurface surface = hw->getEGLSurface();
initializeGL(mEGLDisplay, surface);
initializeGL(mEGLDisplay, hw);
// start the EventThread
mEventThread = new EventThread(this);
@ -863,7 +852,7 @@ void SurfaceFlinger::postFramebuffer()
// FIXME: EGL spec says:
// "surface must be bound to the calling thread's current context,
// for the current rendering API."
DisplayDevice::makeCurrent(getDefaultDisplayDevice(), mEGLContext);
DisplayDevice::makeCurrent(mEGLDisplay, getDefaultDisplayDevice(), mEGLContext);
hwc.commit();
}
@ -983,11 +972,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
if (state.layerStack != draw[i].layerStack) {
disp->setLayerStack(state.layerStack);
}
if (state.orientation != draw[i].orientation ||
state.viewport != draw[i].viewport ||
state.frame != draw[i].frame) {
if (state.orientation != draw[i].orientation) {
disp->setOrientation(state.orientation);
// TODO: take viewport and frame into account
}
if (state.viewport != draw[i].viewport) {
disp->setViewport(state.viewport);
}
if (state.frame != draw[i].frame) {
disp->setFrame(state.frame);
}
}
}
@ -1006,7 +998,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
state.type, display, stc, 0, mEGLConfig);
disp->setLayerStack(state.layerStack);
disp->setOrientation(state.orientation);
// TODO: take viewport and frame into account
disp->setViewport(state.viewport);
disp->setFrame(state.frame);
mDisplays.add(display, disp);
}
}
@ -1280,7 +1273,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
if (hasGlesComposition) {
DisplayDevice::makeCurrent(hw, mEGLContext);
DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
// set the frame buffer
glMatrixMode(GL_MODELVIEW);
@ -1977,15 +1970,18 @@ void SurfaceFlinger::dumpAllLocked(
const sp<const DisplayDevice>& hw(mDisplays[dpy]);
snprintf(buffer, SIZE,
"+ DisplayDevice[%u]\n"
" id=%x, layerStack=%u, (%4dx%4d), orient=%2d, tr=%08x, "
"flips=%u, secure=%d, numLayers=%u\n",
" id=%x, layerStack=%u, (%4dx%4d), orient=%2d (type=%08x), "
"flips=%u, secure=%d, numLayers=%u, v:[%d,%d,%d,%d], f:[%d,%d,%d,%d]\n",
dpy,
hw->getDisplayType(), hw->getLayerStack(),
hw->getWidth(), hw->getHeight(),
hw->getOrientation(), hw->getTransform().getType(),
hw->getPageFlipCount(),
hw->getSecureLayerVisible(),
hw->getVisibleLayersSortedByZ().size());
hw->getVisibleLayersSortedByZ().size(),
hw->getViewport().left, hw->getViewport().top, hw->getViewport().right, hw->getViewport().bottom,
hw->getFrame().left, hw->getFrame().top, hw->getFrame().right, hw->getFrame().bottom);
result.append(buffer);
}
@ -2488,6 +2484,8 @@ SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
: type(type), layerStack(0), orientation(0) {
viewport.makeInvalid();
frame.makeInvalid();
}
// ---------------------------------------------------------------------------

View File

@ -320,7 +320,7 @@ private:
EGLint const* attrs, PixelFormat format, EGLConfig* outConfig);
static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
void initializeGL(EGLDisplay display, EGLSurface surface);
void initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw);
uint32_t getMaxTextureSize() const;
uint32_t getMaxViewportDims() const;