Merge changes Ie03796ae,Ide3e980a into gingerbread
* changes: [3171580] SurfaceFlinger Bypass mode. (DO NOT MERGE) [3171580] Add transform field to native buffers. (DO NOT MERGE)
This commit is contained in:
committed by
Android (Google) Code Review
commit
a2977c383d
@@ -26,6 +26,8 @@
|
||||
#include <utils/Flattenable.h>
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
|
||||
struct android_native_buffer_t;
|
||||
|
||||
namespace android {
|
||||
@@ -63,6 +65,13 @@ public:
|
||||
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK
|
||||
};
|
||||
|
||||
enum {
|
||||
TRANSFORM_IDENTITY = 0,
|
||||
TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
|
||||
TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
|
||||
TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270
|
||||
};
|
||||
|
||||
GraphicBuffer();
|
||||
|
||||
// creates w * h buffer
|
||||
@@ -79,6 +88,7 @@ public:
|
||||
uint32_t getHeight() const { return height; }
|
||||
uint32_t getStride() const { return stride; }
|
||||
uint32_t getUsage() const { return usage; }
|
||||
uint32_t getTransform() const { return transform; }
|
||||
PixelFormat getPixelFormat() const { return format; }
|
||||
Rect getBounds() const { return Rect(width, height); }
|
||||
|
||||
|
||||
@@ -51,8 +51,12 @@ typedef struct android_native_buffer_t
|
||||
int stride;
|
||||
int format;
|
||||
int usage;
|
||||
|
||||
void* reserved[2];
|
||||
|
||||
/* transformation as defined in hardware.h */
|
||||
uint8_t transform;
|
||||
|
||||
uint8_t reserved_bytes[3];
|
||||
void* reserved[1];
|
||||
|
||||
buffer_handle_t handle;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ GraphicBuffer::GraphicBuffer()
|
||||
stride =
|
||||
format =
|
||||
usage = 0;
|
||||
transform = 0;
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
@@ -57,7 +58,8 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
|
||||
height =
|
||||
stride =
|
||||
format =
|
||||
usage = 0;
|
||||
usage =
|
||||
transform = 0;
|
||||
handle = NULL;
|
||||
mInitCheck = initSize(w, h, reqFormat, reqUsage);
|
||||
}
|
||||
@@ -74,6 +76,7 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
|
||||
stride = inStride;
|
||||
format = inFormat;
|
||||
usage = inUsage;
|
||||
transform = 0;
|
||||
handle = inHandle;
|
||||
}
|
||||
|
||||
@@ -182,8 +185,10 @@ status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage)
|
||||
return res;
|
||||
}
|
||||
|
||||
const int kFlattenFdsOffset = 9;
|
||||
|
||||
size_t GraphicBuffer::getFlattenedSize() const {
|
||||
return (8 + (handle ? handle->numInts : 0))*sizeof(int);
|
||||
return (kFlattenFdsOffset + (handle ? handle->numInts : 0))*sizeof(int);
|
||||
}
|
||||
|
||||
size_t GraphicBuffer::getFdCount() const {
|
||||
@@ -208,13 +213,14 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size,
|
||||
buf[5] = usage;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = transform;
|
||||
|
||||
if (handle) {
|
||||
buf[6] = handle->numFds;
|
||||
buf[7] = handle->numInts;
|
||||
native_handle_t const* const h = handle;
|
||||
memcpy(fds, h->data, h->numFds*sizeof(int));
|
||||
memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
|
||||
memcpy(&buf[kFlattenFdsOffset], h->data + h->numFds, h->numInts*sizeof(int));
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
@@ -223,7 +229,7 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size,
|
||||
status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
|
||||
int fds[], size_t count)
|
||||
{
|
||||
if (size < 8*sizeof(int)) return NO_MEMORY;
|
||||
if (size < kFlattenFdsOffset*sizeof(int)) return NO_MEMORY;
|
||||
|
||||
int const* buf = static_cast<int const*>(buffer);
|
||||
if (buf[0] != 'GBFR') return BAD_TYPE;
|
||||
@@ -231,7 +237,7 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
|
||||
const size_t numFds = buf[6];
|
||||
const size_t numInts = buf[7];
|
||||
|
||||
const size_t sizeNeeded = (8 + numInts) * sizeof(int);
|
||||
const size_t sizeNeeded = (kFlattenFdsOffset + numInts) * sizeof(int);
|
||||
if (size < sizeNeeded) return NO_MEMORY;
|
||||
|
||||
size_t fdCountNeeded = 0;
|
||||
@@ -248,9 +254,10 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
|
||||
stride = buf[3];
|
||||
format = buf[4];
|
||||
usage = buf[5];
|
||||
transform = buf[8];
|
||||
native_handle* h = native_handle_create(numFds, numInts);
|
||||
memcpy(h->data, fds, numFds*sizeof(int));
|
||||
memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));
|
||||
memcpy(h->data + numFds, &buf[kFlattenFdsOffset], numInts*sizeof(int));
|
||||
handle = h;
|
||||
} else {
|
||||
width = height = stride = format = usage = 0;
|
||||
|
||||
@@ -25,6 +25,7 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3)
|
||||
endif
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
|
||||
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
|
||||
LOCAL_CFLAGS += -DUSE_COMPOSITION_BYPASS
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@@ -339,6 +339,12 @@ void DisplayHardware::flip(const Region& dirty) const
|
||||
//glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
status_t DisplayHardware::postBypassBuffer(const native_handle_t* handle) const
|
||||
{
|
||||
framebuffer_device_t *fbDev = (framebuffer_device_t *)mNativeWindow->getDevice();
|
||||
return fbDev->post(fbDev, handle);
|
||||
}
|
||||
|
||||
uint32_t DisplayHardware::getFlags() const
|
||||
{
|
||||
return mFlags;
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
// Flip the front and back buffers if the back buffer is "dirty". Might
|
||||
// be instantaneous, might involve copying the frame buffer around.
|
||||
void flip(const Region& dirty) const;
|
||||
status_t postBypassBuffer(const native_handle_t* handle) const;
|
||||
|
||||
float getDpiX() const;
|
||||
float getDpiY() const;
|
||||
|
||||
@@ -57,7 +57,8 @@ Layer::Layer(SurfaceFlinger* flinger,
|
||||
mSecure(false),
|
||||
mTextureManager(),
|
||||
mBufferManager(mTextureManager),
|
||||
mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false)
|
||||
mWidth(0), mHeight(0), mNeedsScaling(false), mFixedSize(false),
|
||||
mBypassState(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -251,6 +252,29 @@ void Layer::onDraw(const Region& clip) const
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_COMPOSITION_BYPASS
|
||||
sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
|
||||
if ((buffer != NULL) && (buffer->transform)) {
|
||||
// Here we have a "bypass" buffer, but we need to composite it
|
||||
// most likely because it's not fullscreen anymore.
|
||||
// Since the buffer may have a transformation applied by the client
|
||||
// we need to inverse this transformation here.
|
||||
|
||||
// calculate the inverse of the buffer transform
|
||||
const uint32_t mask = HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
|
||||
const uint32_t bufferTransformInverse = buffer->transform ^ mask;
|
||||
|
||||
// To accomplish the inverse transform, we use "mBufferTransform"
|
||||
// which is not used by Layer.cpp
|
||||
const_cast<Layer*>(this)->mBufferTransform = bufferTransformInverse;
|
||||
drawWithOpenGL(clip, tex);
|
||||
// reset to "no transfrom"
|
||||
const_cast<Layer*>(this)->mBufferTransform = 0;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
drawWithOpenGL(clip, tex);
|
||||
}
|
||||
|
||||
@@ -311,11 +335,12 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
|
||||
* buffer 'index' as our front buffer.
|
||||
*/
|
||||
|
||||
status_t err = NO_ERROR;
|
||||
uint32_t w, h, f;
|
||||
uint32_t w, h, f, bypass;
|
||||
{ // scope for the lock
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
bypass = mBypassState;
|
||||
|
||||
// zero means default
|
||||
mFixedSize = reqWidth && reqHeight;
|
||||
if (!reqFormat) reqFormat = mFormat;
|
||||
@@ -340,9 +365,40 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
|
||||
// here we have to reallocate a new buffer because the buffer could be
|
||||
// used as the front buffer, or by a client in our process
|
||||
// (eg: status bar), and we can't release the handle under its feet.
|
||||
const uint32_t effectiveUsage = getEffectiveUsage(usage);
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
|
||||
err = buffer->initCheck();
|
||||
uint32_t effectiveUsage = getEffectiveUsage(usage);
|
||||
|
||||
status_t err = NO_MEMORY;
|
||||
|
||||
#ifdef USE_COMPOSITION_BYPASS
|
||||
if (!mSecure && bypass && (effectiveUsage & GRALLOC_USAGE_HW_RENDER)) {
|
||||
// always allocate a buffer matching the screen size. the size
|
||||
// may be different from (w,h) if the buffer is rotated.
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
int32_t w = hw.getWidth();
|
||||
int32_t h = hw.getHeight();
|
||||
int32_t f = hw.getFormat();
|
||||
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage | GRALLOC_USAGE_HW_FB);
|
||||
err = buffer->initCheck();
|
||||
buffer->transform = uint8_t(getOrientation());
|
||||
|
||||
if (err != NO_ERROR) {
|
||||
// allocation didn't succeed, probably because an older bypass
|
||||
// window hasn't released all its resources yet.
|
||||
ClientRef::Access sharedClient(mUserClientRef);
|
||||
SharedBufferServer* lcblk(sharedClient.get());
|
||||
if (lcblk) {
|
||||
// all buffers need reallocation
|
||||
lcblk->reallocateAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (err != NO_ERROR) {
|
||||
buffer = new GraphicBuffer(w, h, f, effectiveUsage);
|
||||
err = buffer->initCheck();
|
||||
}
|
||||
|
||||
if (err || buffer->handle == 0) {
|
||||
GraphicBuffer::dumpAllocationsToSystemLog();
|
||||
@@ -389,6 +445,27 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
|
||||
return usage;
|
||||
}
|
||||
|
||||
bool Layer::setBypass(bool enable)
|
||||
{
|
||||
Mutex::Autolock _l(mLock);
|
||||
|
||||
if (mNeedsScaling || mNeedsFiltering) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mBypassState != enable) {
|
||||
mBypassState = enable;
|
||||
ClientRef::Access sharedClient(mUserClientRef);
|
||||
SharedBufferServer* lcblk(sharedClient.get());
|
||||
if (lcblk) {
|
||||
// all buffers need reallocation
|
||||
lcblk->reallocateAll();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t Layer::doTransaction(uint32_t flags)
|
||||
{
|
||||
const Layer::State& front(drawingState());
|
||||
@@ -639,9 +716,9 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||
snprintf(buffer, SIZE,
|
||||
" "
|
||||
"format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
|
||||
" freezeLock=%p, dq-q-time=%u us\n",
|
||||
" freezeLock=%p, bypass=%d, dq-q-time=%u us\n",
|
||||
mFormat, w0, h0, s0, w1, h1, s1,
|
||||
getFreezeLock().get(), totalTime);
|
||||
getFreezeLock().get(), mBypassState, totalTime);
|
||||
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@ public:
|
||||
virtual sp<Surface> createSurface() const;
|
||||
virtual status_t ditch();
|
||||
virtual void onRemoved();
|
||||
virtual bool setBypass(bool enable);
|
||||
|
||||
inline sp<GraphicBuffer> getBypassBuffer() const {
|
||||
return mBufferManager.getActiveBuffer(); }
|
||||
|
||||
// only for debugging
|
||||
inline sp<GraphicBuffer> getBuffer(int i) const {
|
||||
@@ -232,6 +236,7 @@ private:
|
||||
uint32_t mReqFormat;
|
||||
bool mNeedsScaling;
|
||||
bool mFixedSize;
|
||||
bool mBypassState;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
|
||||
#include "DisplayHardware/DisplayHardware.h"
|
||||
#include "Transform.h"
|
||||
|
||||
namespace android {
|
||||
@@ -117,6 +118,11 @@ public:
|
||||
virtual void draw(const Region& clip) const;
|
||||
virtual void drawForSreenShot() const;
|
||||
|
||||
/**
|
||||
* bypass mode
|
||||
*/
|
||||
virtual bool setBypass(bool enable) { return false; }
|
||||
|
||||
/**
|
||||
* onDraw - draws the surface.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,10 @@
|
||||
#define AID_GRAPHICS 1003
|
||||
#endif
|
||||
|
||||
#ifdef USE_COMPOSITION_BYPASS
|
||||
#warning "using COMPOSITION_BYPASS"
|
||||
#endif
|
||||
|
||||
#define DISPLAY_COUNT 1
|
||||
|
||||
namespace android {
|
||||
@@ -373,8 +377,15 @@ bool SurfaceFlinger::threadLoop()
|
||||
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
if (LIKELY(hw.canDraw() && !isFrozen())) {
|
||||
// repaint the framebuffer (if needed)
|
||||
|
||||
#ifdef USE_COMPOSITION_BYPASS
|
||||
if (handleBypassLayer()) {
|
||||
unlockClients();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// repaint the framebuffer (if needed)
|
||||
const int index = hw.getCurrentBufferIndex();
|
||||
GraphicLog& logger(GraphicLog::getInstance());
|
||||
|
||||
@@ -401,6 +412,20 @@ bool SurfaceFlinger::threadLoop()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SurfaceFlinger::handleBypassLayer()
|
||||
{
|
||||
sp<Layer> bypassLayer(mBypassLayer.promote());
|
||||
if (bypassLayer != 0) {
|
||||
sp<GraphicBuffer> buffer(bypassLayer->getBypassBuffer());
|
||||
if (buffer!=0 && (buffer->usage & GRALLOC_USAGE_HW_FB)) {
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
hw.postBypassBuffer(buffer->handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SurfaceFlinger::postFramebuffer()
|
||||
{
|
||||
if (!mInvalidRegion.isEmpty()) {
|
||||
@@ -696,6 +721,28 @@ void SurfaceFlinger::commitTransaction()
|
||||
mTransactionCV.broadcast();
|
||||
}
|
||||
|
||||
void SurfaceFlinger::setBypassLayer(const sp<LayerBase>& layer)
|
||||
{
|
||||
// if this layer is already the bypass layer, do nothing
|
||||
sp<Layer> cur(mBypassLayer.promote());
|
||||
if (mBypassLayer == layer)
|
||||
return;
|
||||
|
||||
// clear the current bypass layer
|
||||
mBypassLayer.clear();
|
||||
if (cur != 0) {
|
||||
cur->setBypass(false);
|
||||
cur.clear();
|
||||
}
|
||||
|
||||
// set new bypass layer
|
||||
if (layer != 0) {
|
||||
if (layer->setBypass(true)) {
|
||||
mBypassLayer = static_cast<Layer*>(layer.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceFlinger::handlePageFlip()
|
||||
{
|
||||
bool visibleRegions = mVisibleRegionsDirty;
|
||||
@@ -721,6 +768,21 @@ void SurfaceFlinger::handlePageFlip()
|
||||
mVisibleLayersSortedByZ.add(currentLayers[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_COMPOSITION_BYPASS
|
||||
sp<LayerBase> bypassLayer;
|
||||
const size_t numVisibleLayers = mVisibleLayersSortedByZ.size();
|
||||
if (numVisibleLayers == 1) {
|
||||
const sp<LayerBase>& candidate(mVisibleLayersSortedByZ[0]);
|
||||
const Region& visibleRegion(candidate->visibleRegionScreen);
|
||||
const Region reminder(screenRegion.subtract(visibleRegion));
|
||||
if (reminder.isEmpty()) {
|
||||
// fullscreen candidate!
|
||||
bypassLayer = candidate;
|
||||
}
|
||||
}
|
||||
setBypassLayer(bypassLayer);
|
||||
#endif
|
||||
|
||||
mWormholeRegion = screenRegion.subtract(opaqueRegion);
|
||||
mVisibleRegionsDirty = false;
|
||||
}
|
||||
@@ -1416,9 +1478,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
||||
mWormholeRegion.dump(result, "WormholeRegion");
|
||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||
snprintf(buffer, SIZE,
|
||||
" display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
|
||||
" display frozen: %s, freezeCount=%d, orientation=%d, bypass=%p, canDraw=%d\n",
|
||||
mFreezeDisplay?"yes":"no", mFreezeCount,
|
||||
mCurrentState.orientation, hw.canDraw());
|
||||
mCurrentState.orientation, mBypassLayer.unsafe_get(), hw.canDraw());
|
||||
result.append(buffer);
|
||||
snprintf(buffer, SIZE,
|
||||
" last eglSwapBuffers() time: %f us\n"
|
||||
|
||||
@@ -307,6 +307,7 @@ private:
|
||||
bool lockPageFlip(const LayerVector& currentLayers);
|
||||
void unlockPageFlip(const LayerVector& currentLayers);
|
||||
void handleRepaint();
|
||||
bool handleBypassLayer();
|
||||
void postFramebuffer();
|
||||
void composeSurfaces(const Region& dirty);
|
||||
void unlockClients();
|
||||
@@ -322,6 +323,7 @@ private:
|
||||
uint32_t setTransactionFlags(uint32_t flags);
|
||||
void commitTransaction();
|
||||
|
||||
void setBypassLayer(const sp<LayerBase>& layer);
|
||||
|
||||
status_t captureScreenImplLocked(DisplayID dpy,
|
||||
sp<IMemoryHeap>* heap,
|
||||
@@ -399,6 +401,7 @@ private:
|
||||
int32_t mFreezeCount;
|
||||
nsecs_t mFreezeDisplayTime;
|
||||
Vector< sp<LayerBase> > mVisibleLayersSortedByZ;
|
||||
wp<Layer> mBypassLayer;
|
||||
|
||||
|
||||
// don't use a lock for these, we don't care
|
||||
|
||||
Reference in New Issue
Block a user