call into hwcomposer HAL when present
Change-Id: I70f31c69a9436a43860e78977442863ecba6d27b
This commit is contained in:
parent
bc7e31a84b
commit
a350ff9869
@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
|
||||
clz.cpp.arm \
|
||||
DisplayHardware/DisplayHardware.cpp \
|
||||
DisplayHardware/DisplayHardwareBase.cpp \
|
||||
DisplayHardware/HWComposer.cpp \
|
||||
BlurFilter.cpp.arm \
|
||||
GLExtensions.cpp \
|
||||
Layer.cpp \
|
||||
|
@ -36,11 +36,11 @@
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
|
||||
#include <hardware/copybit.h>
|
||||
#include <hardware/overlay.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include "GLExtensions.h"
|
||||
#include "HWComposer.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
@ -76,7 +76,7 @@ DisplayHardware::DisplayHardware(
|
||||
const sp<SurfaceFlinger>& flinger,
|
||||
uint32_t dpy)
|
||||
: DisplayHardwareBase(flinger, dpy),
|
||||
mFlags(0)
|
||||
mFlags(0), mHwc(0)
|
||||
{
|
||||
init(dpy);
|
||||
}
|
||||
@ -262,6 +262,17 @@ void DisplayHardware::init(uint32_t dpy)
|
||||
|
||||
// Unbind the context from this thread
|
||||
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
|
||||
// initialize the H/W composer
|
||||
mHwc = new HWComposer();
|
||||
if (mHwc->initCheck() == NO_ERROR) {
|
||||
mHwc->setFrameBuffer(mDisplay, mSurface);
|
||||
}
|
||||
}
|
||||
|
||||
HWComposer& DisplayHardware::getHwComposer() const {
|
||||
return *mHwc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -317,7 +328,12 @@ void DisplayHardware::flip(const Region& dirty) const
|
||||
}
|
||||
|
||||
mPageFlipCount++;
|
||||
eglSwapBuffers(dpy, surface);
|
||||
|
||||
if (mHwc->initCheck() == NO_ERROR) {
|
||||
mHwc->commit();
|
||||
} else {
|
||||
eglSwapBuffers(dpy, surface);
|
||||
}
|
||||
checkEGLErrors("eglSwapBuffers");
|
||||
|
||||
// for debugging
|
||||
|
@ -34,12 +34,11 @@
|
||||
#include "DisplayHardware/DisplayHardwareBase.h"
|
||||
|
||||
struct overlay_control_device_t;
|
||||
struct framebuffer_device_t;
|
||||
struct copybit_image_t;
|
||||
|
||||
namespace android {
|
||||
|
||||
class FramebufferNativeWindow;
|
||||
class HWComposer;
|
||||
|
||||
class DisplayHardware : public DisplayHardwareBase
|
||||
{
|
||||
@ -80,6 +79,9 @@ public:
|
||||
uint32_t getPageFlipCount() const;
|
||||
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
||||
overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
|
||||
|
||||
// Hardware Composer
|
||||
HWComposer& getHwComposer() const;
|
||||
|
||||
status_t compositionComplete() const;
|
||||
|
||||
@ -107,6 +109,8 @@ private:
|
||||
GLint mMaxViewportDims;
|
||||
GLint mMaxTextureSize;
|
||||
|
||||
HWComposer* mHwc;
|
||||
|
||||
sp<FramebufferNativeWindow> mNativeWindow;
|
||||
overlay_control_device_t* mOverlayEngine;
|
||||
};
|
||||
|
93
services/surfaceflinger/DisplayHardware/HWComposer.cpp
Normal file
93
services/surfaceflinger/DisplayHardware/HWComposer.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 <sys/types.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "HWComposer.h"
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
HWComposer::HWComposer()
|
||||
: mModule(0), mHwc(0), mList(0),
|
||||
mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
|
||||
{
|
||||
int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
|
||||
LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
|
||||
if (err == 0) {
|
||||
err = hwc_open(mModule, &mHwc);
|
||||
LOGE_IF(err, "%s device failed to initialize (%s)",
|
||||
HWC_HARDWARE_COMPOSER, strerror(-err));
|
||||
}
|
||||
}
|
||||
|
||||
HWComposer::~HWComposer() {
|
||||
free(mList);
|
||||
if (mHwc) {
|
||||
hwc_close(mHwc);
|
||||
}
|
||||
}
|
||||
|
||||
status_t HWComposer::initCheck() const {
|
||||
return mHwc ? NO_ERROR : NO_INIT;
|
||||
}
|
||||
|
||||
void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
|
||||
mDpy = (hwc_display_t)dpy;
|
||||
mSur = (hwc_surface_t)sur;
|
||||
}
|
||||
|
||||
status_t HWComposer::createWorkList(size_t numLayers) {
|
||||
if (mHwc && (!mList || mList->numHwLayers < numLayers)) {
|
||||
free(mList);
|
||||
size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
|
||||
mList = (hwc_layer_list_t*)malloc(size);
|
||||
mList->flags = HWC_GEOMETRY_CHANGED;
|
||||
mList->numHwLayers = numLayers;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t HWComposer::prepare() const {
|
||||
int err = mHwc->prepare(mHwc, mList);
|
||||
return (status_t)err;
|
||||
}
|
||||
|
||||
status_t HWComposer::commit() const {
|
||||
int err = mHwc->set(mHwc, mDpy, mSur, mList);
|
||||
mList->flags &= ~HWC_GEOMETRY_CHANGED;
|
||||
return (status_t)err;
|
||||
}
|
||||
|
||||
HWComposer::iterator HWComposer::begin() {
|
||||
return mList ? &(mList->hwLayers[0]) : NULL;
|
||||
}
|
||||
|
||||
HWComposer::iterator HWComposer::end() {
|
||||
return mList ? &(mList->hwLayers[mList->numHwLayers]) : NULL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
70
services/surfaceflinger/DisplayHardware/HWComposer.h
Normal file
70
services/surfaceflinger/DisplayHardware/HWComposer.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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_SF_HWCOMPOSER_H
|
||||
#define ANDROID_SF_HWCOMPOSER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <hardware/hwcomposer.h>
|
||||
|
||||
namespace android {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class HWComposer
|
||||
{
|
||||
public:
|
||||
|
||||
HWComposer();
|
||||
~HWComposer();
|
||||
|
||||
status_t initCheck() const;
|
||||
|
||||
// tells the HAL what the framebuffer is
|
||||
void setFrameBuffer(EGLDisplay dpy, EGLSurface sur);
|
||||
|
||||
// create a work list for numLayers layer
|
||||
status_t createWorkList(size_t numLayers);
|
||||
|
||||
// Asks the HAL what it can do
|
||||
status_t prepare() const;
|
||||
|
||||
// commits the list
|
||||
status_t commit() const;
|
||||
|
||||
|
||||
typedef hwc_layer_t const * const_iterator;
|
||||
typedef hwc_layer_t* iterator;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
private:
|
||||
hw_module_t const* mModule;
|
||||
hwc_composer_device_t* mHwc;
|
||||
hwc_layer_list_t* mList;
|
||||
hwc_display_t mDpy;
|
||||
hwc_surface_t mSur;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_SF_HWCOMPOSER_H
|
@ -35,6 +35,7 @@
|
||||
#include "Layer.h"
|
||||
#include "SurfaceFlinger.h"
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
|
||||
|
||||
#define DEBUG_RESIZE 0
|
||||
@ -177,6 +178,62 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void Layer::setGeometry(hwc_layer_t* hwcl)
|
||||
{
|
||||
hwcl->compositionType = HWC_FRAMEBUFFER;
|
||||
hwcl->hints = 0;
|
||||
hwcl->flags = 0;
|
||||
hwcl->transform = 0;
|
||||
hwcl->blending = HWC_BLENDING_NONE;
|
||||
|
||||
// we can't do alpha-fade with the hwc HAL
|
||||
const State& s(drawingState());
|
||||
if (s.alpha < 0xFF) {
|
||||
hwcl->flags = HWC_SKIP_LAYER;
|
||||
return;
|
||||
}
|
||||
|
||||
// we can only handle simple transformation
|
||||
if (mOrientation & Transform::ROT_INVALID) {
|
||||
hwcl->flags = HWC_SKIP_LAYER;
|
||||
return;
|
||||
}
|
||||
|
||||
hwcl->transform = mOrientation;
|
||||
|
||||
if (needsBlending()) {
|
||||
hwcl->blending = mPremultipliedAlpha ?
|
||||
HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
|
||||
}
|
||||
|
||||
hwcl->displayFrame.left = mTransformedBounds.left;
|
||||
hwcl->displayFrame.top = mTransformedBounds.top;
|
||||
hwcl->displayFrame.right = mTransformedBounds.right;
|
||||
hwcl->displayFrame.bottom = mTransformedBounds.bottom;
|
||||
|
||||
hwcl->visibleRegionScreen.rects =
|
||||
reinterpret_cast<hwc_rect_t const *>(
|
||||
visibleRegionScreen.getArray(
|
||||
&hwcl->visibleRegionScreen.numRects));
|
||||
}
|
||||
|
||||
void Layer::setPerFrameData(hwc_layer_t* hwcl) {
|
||||
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
|
||||
if (buffer == NULL) {
|
||||
// this situation can happen if we ran out of memory for instance.
|
||||
// not much we can do. continue to use whatever texture was bound
|
||||
// to this context.
|
||||
hwcl->handle = NULL;
|
||||
return;
|
||||
}
|
||||
hwcl->handle = const_cast<native_handle_t*>(buffer->handle);
|
||||
// TODO: set the crop value properly
|
||||
hwcl->sourceCrop.left = 0;
|
||||
hwcl->sourceCrop.top = 0;
|
||||
hwcl->sourceCrop.right = buffer->width;
|
||||
hwcl->sourceCrop.bottom = buffer->height;
|
||||
}
|
||||
|
||||
void Layer::reloadTexture(const Region& dirty)
|
||||
{
|
||||
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
bool isFixedSize() const;
|
||||
|
||||
// LayerBase interface
|
||||
virtual void setGeometry(hwc_layer_t* hwcl);
|
||||
virtual void setPerFrameData(hwc_layer_t* hwcl);
|
||||
virtual void onDraw(const Region& clip) const;
|
||||
virtual uint32_t doTransaction(uint32_t transactionFlags);
|
||||
virtual void lockPageFlip(bool& recomputeVisibleRegions);
|
||||
|
@ -307,6 +307,15 @@ void LayerBase::drawRegion(const Region& reg) const
|
||||
}
|
||||
}
|
||||
|
||||
void LayerBase::setGeometry(hwc_layer_t* hwcl) {
|
||||
hwcl->flags |= HWC_SKIP_LAYER;
|
||||
}
|
||||
|
||||
void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
|
||||
hwcl->compositionType = HWC_FRAMEBUFFER;
|
||||
hwcl->handle = NULL;
|
||||
}
|
||||
|
||||
void LayerBase::draw(const Region& clip) const
|
||||
{
|
||||
// reset GL state
|
||||
|
@ -35,6 +35,8 @@
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <hardware/hwcomposer.h>
|
||||
|
||||
#include "Transform.h"
|
||||
|
||||
namespace android {
|
||||
@ -108,6 +110,10 @@ public:
|
||||
|
||||
virtual const char* getTypeId() const { return "LayerBase"; }
|
||||
|
||||
virtual void setGeometry(hwc_layer_t* hwcl);
|
||||
|
||||
virtual void setPerFrameData(hwc_layer_t* hwcl);
|
||||
|
||||
/**
|
||||
* draw - performs some global clipping optimizations
|
||||
* and calls onDraw().
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "SurfaceFlinger.h"
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
|
||||
/* ideally AID_GRAPHICS would be in a semi-public header
|
||||
* or there would be a way to map a user/group name to its id
|
||||
@ -76,6 +77,7 @@ SurfaceFlinger::SurfaceFlinger()
|
||||
mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
|
||||
mDump("android.permission.DUMP"),
|
||||
mVisibleRegionsDirty(false),
|
||||
mHwWorkListDirty(false),
|
||||
mDeferReleaseConsole(false),
|
||||
mFreezeDisplay(false),
|
||||
mFreezeCount(0),
|
||||
@ -368,6 +370,11 @@ bool SurfaceFlinger::threadLoop()
|
||||
// post surfaces (if needed)
|
||||
handlePageFlip();
|
||||
|
||||
if (UNLIKELY(mHwWorkListDirty)) {
|
||||
// build the h/w work list
|
||||
handleWorkList();
|
||||
}
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
if (LIKELY(hw.canDraw() && !isFrozen())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
@ -443,6 +450,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
handleTransactionLocked(transactionFlags, ditchedLayers);
|
||||
mLastTransactionTime = systemTime() - now;
|
||||
mDebugInTransaction = 0;
|
||||
mHwWorkListDirty = true;
|
||||
// here the transaction has been committed
|
||||
}
|
||||
|
||||
@ -450,6 +458,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||
* Clean-up all layers that went away
|
||||
* (do this without the lock held)
|
||||
*/
|
||||
|
||||
const size_t count = ditchedLayers.size();
|
||||
for (size_t i=0 ; i<count ; i++) {
|
||||
if (ditchedLayers[i] != 0) {
|
||||
@ -683,8 +692,8 @@ void SurfaceFlinger::commitTransaction()
|
||||
void SurfaceFlinger::handlePageFlip()
|
||||
{
|
||||
bool visibleRegions = mVisibleRegionsDirty;
|
||||
LayerVector& currentLayers = const_cast<LayerVector&>(
|
||||
mDrawingState.layersSortedByZ);
|
||||
LayerVector& currentLayers(
|
||||
const_cast<LayerVector&>(mDrawingState.layersSortedByZ));
|
||||
visibleRegions |= lockPageFlip(currentLayers);
|
||||
|
||||
const DisplayHardware& hw = graphicPlane(0).displayHardware();
|
||||
@ -707,6 +716,7 @@ void SurfaceFlinger::handlePageFlip()
|
||||
|
||||
mWormholeRegion = screenRegion.subtract(opaqueRegion);
|
||||
mVisibleRegionsDirty = false;
|
||||
mHwWorkListDirty = true;
|
||||
}
|
||||
|
||||
unlockPageFlip(currentLayers);
|
||||
@ -737,6 +747,21 @@ void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleWorkList()
|
||||
{
|
||||
mHwWorkListDirty = false;
|
||||
HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
|
||||
if (hwc.initCheck() == NO_ERROR) {
|
||||
const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
|
||||
const size_t count = currentLayers.size();
|
||||
hwc.createWorkList(count);
|
||||
HWComposer::iterator cur(hwc.begin());
|
||||
HWComposer::iterator last(hwc.end());
|
||||
for (size_t i=0 ; (i<count) && (cur!=last) ; ++i, ++cur) {
|
||||
currentLayers[i]->setGeometry(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handleRepaint()
|
||||
{
|
||||
@ -801,15 +826,63 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
|
||||
// draw something...
|
||||
drawWormhole();
|
||||
}
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
|
||||
const size_t count = layers.size();
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
HWComposer& hwc(hw.getHwComposer());
|
||||
HWComposer::iterator cur(hwc.begin());
|
||||
HWComposer::iterator last(hwc.end());
|
||||
|
||||
// update the per-frame h/w composer data for each layer
|
||||
if (cur != last) {
|
||||
for (size_t i=0 ; i<count && cur!=last ; ++i, ++cur) {
|
||||
layers[i]->setPerFrameData(cur);
|
||||
}
|
||||
err = hwc.prepare();
|
||||
LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
|
||||
}
|
||||
|
||||
// and then, render the layers targeted at the framebuffer
|
||||
Region transparent(hw.bounds());
|
||||
for (size_t i=0 ; i<count ; ++i) {
|
||||
|
||||
// see if we need to skip this layer
|
||||
if (!err && cur != last) {
|
||||
if (!((cur->compositionType == HWC_FRAMEBUFFER) ||
|
||||
(cur->flags & HWC_SKIP_LAYER))) {
|
||||
++cur;
|
||||
continue;
|
||||
}
|
||||
++cur;
|
||||
}
|
||||
|
||||
// draw the layer into the framebuffer
|
||||
const sp<LayerBase>& layer(layers[i]);
|
||||
transparent.subtractSelf(layer->visibleRegionScreen);
|
||||
const Region clip(dirty.intersect(layer->visibleRegionScreen));
|
||||
if (!clip.isEmpty()) {
|
||||
layer->draw(clip);
|
||||
}
|
||||
}
|
||||
|
||||
// finally clear everything we didn't draw as a result of calling
|
||||
// prepare (this leaves the FB transparent).
|
||||
transparent.andSelf(dirty);
|
||||
if (!transparent.isEmpty()) {
|
||||
glClearColor(0,0,0,0);
|
||||
Region::const_iterator it = transparent.begin();
|
||||
Region::const_iterator const end = transparent.end();
|
||||
const int32_t height = hw.getHeight();
|
||||
while (it != end) {
|
||||
const Rect& r(*it++);
|
||||
const GLint sy = height - (r.top + r.height());
|
||||
glScissor(r.left, sy, r.width(), r.height());
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::unlockClients()
|
||||
|
@ -296,6 +296,7 @@ private:
|
||||
void handlePageFlip();
|
||||
bool lockPageFlip(const LayerVector& currentLayers);
|
||||
void unlockPageFlip(const LayerVector& currentLayers);
|
||||
void handleWorkList();
|
||||
void handleRepaint();
|
||||
void postFramebuffer();
|
||||
void composeSurfaces(const Region& dirty);
|
||||
@ -370,6 +371,7 @@ private:
|
||||
Region mInvalidRegion;
|
||||
Region mWormholeRegion;
|
||||
bool mVisibleRegionsDirty;
|
||||
bool mHwWorkListDirty;
|
||||
bool mDeferReleaseConsole;
|
||||
bool mFreezeDisplay;
|
||||
int32_t mFreezeCount;
|
||||
|
Loading…
Reference in New Issue
Block a user