Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99c7dbb2 authored by Jesse Hall's avatar Jesse Hall
Browse files

Add DisplaySurface abstraction

DisplayDevice now has a DisplaySurface instead of using
FramebufferSurface directly. FramebufferSurface implements
DisplaySurface, and so does the new VirtualDisplaySurface class.
DisplayDevice now always has a surface, not just for virtual displays.

In this change VirtualDisplaySurface is just a stub; buffers still go
directly from GLES to the final consumer.

Bug: 8384764
Change-Id: I57cb668edbc6c37bfebda90b9222d435bf589f37
parent 4c00cc11
Loading
Loading
Loading
Loading
+16 −16
Original line number Diff line number Diff line
@@ -6,18 +6,18 @@ LOCAL_SRC_FILES:= \
    DisplayDevice.cpp \
    EventThread.cpp \
    FrameTracker.cpp \
    GLExtensions.cpp \
    Layer.cpp \
    LayerDim.cpp \
    DisplayHardware/FramebufferSurface.cpp  \
    DisplayHardware/HWComposer.cpp          \
    DisplayHardware/PowerHAL.cpp            \
    GLExtensions.cpp                        \
    MessageQueue.cpp \
    SurfaceFlinger.cpp \
    SurfaceFlingerConsumer.cpp \
    SurfaceTextureLayer.cpp \
    Transform.cpp \
    
    DisplayHardware/FramebufferSurface.cpp \
    DisplayHardware/HWComposer.cpp \
    DisplayHardware/PowerHAL.cpp \
    DisplayHardware/VirtualDisplaySurface.cpp \

LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+31 −44
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@

#include <hardware/gralloc.h>

#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h"

#include "clz.h"
@@ -72,14 +72,12 @@ DisplayDevice::DisplayDevice(
        DisplayType type,
        bool isSecure,
        const wp<IBinder>& displayToken,
        const sp<ANativeWindow>& nativeWindow,
        const sp<FramebufferSurface>& framebufferSurface,
        const sp<DisplaySurface>& displaySurface,
        EGLConfig config)
    : mFlinger(flinger),
      mType(type), mHwcDisplayId(-1),
      mDisplayToken(displayToken),
      mNativeWindow(nativeWindow),
      mFramebufferSurface(framebufferSurface),
      mDisplaySurface(displaySurface),
      mDisplay(EGL_NO_DISPLAY),
      mSurface(EGL_NO_SURFACE),
      mContext(EGL_NO_CONTEXT),
@@ -92,6 +90,7 @@ DisplayDevice::DisplayDevice(
      mLayerStack(NO_LAYER_STACK),
      mOrientation()
{
    mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
    init(config);
}

@@ -183,10 +182,7 @@ uint32_t DisplayDevice::getPageFlipCount() const {
}

status_t DisplayDevice::compositionComplete() const {
    if (mFramebufferSurface == NULL) {
        return NO_ERROR;
    }
    return mFramebufferSurface->compositionComplete();
    return mDisplaySurface->compositionComplete();
}

void DisplayDevice::flip(const Region& dirty) const
@@ -209,45 +205,38 @@ void DisplayDevice::flip(const Region& dirty) const
}

void DisplayDevice::swapBuffers(HWComposer& hwc) const {
    EGLBoolean success = EGL_TRUE;
    if (hwc.initCheck() != NO_ERROR) {
        // no HWC, we call eglSwapBuffers()
        success = eglSwapBuffers(mDisplay, mSurface);
    } else {
        // We have a valid HWC, but not all displays can use it, in particular
        // the virtual displays are on their own.
        // TODO: HWC 1.2 will allow virtual displays
        if (mType >= DisplayDevice::DISPLAY_VIRTUAL) {
            // always call eglSwapBuffers() for virtual displays
            success = eglSwapBuffers(mDisplay, mSurface);
        } else if (hwc.supportsFramebufferTarget()) {
            // as of hwc 1.1 we always call eglSwapBuffers if we have some
            // GLES layers
            if (hwc.hasGlesComposition(mType)) {
                success = eglSwapBuffers(mDisplay, mSurface);
            }
        } else {
            // HWC doesn't have the framebuffer target, we don't call
            // eglSwapBuffers(), since this is handled by HWComposer::commit().
        }
    }

    // We need to call eglSwapBuffers() unless:
    // (a) there was no GLES composition this frame, or
    // (b) we're using a legacy HWC with no framebuffer target support (in
    //     which case HWComposer::commit() handles things).
    if (hwc.initCheck() != NO_ERROR ||
            (hwc.hasGlesComposition(mHwcDisplayId) &&
             hwc.supportsFramebufferTarget())) {
        EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
        if (!success) {
            EGLint error = eglGetError();
            if (error == EGL_CONTEXT_LOST ||
                    mType == DisplayDevice::DISPLAY_PRIMARY) {
                LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
                        mDisplay, mSurface, error);
            } else {
                ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
                        mDisplay, mSurface, error);
            }
        }
    }

    status_t result = mDisplaySurface->advanceFrame();
    if (result != NO_ERROR) {
        ALOGE("[%s] failed pushing new frame to HWC: %d",
                mDisplayName.string(), result);
    }
}

void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
    if (hwc.initCheck() == NO_ERROR) {
        if (mFramebufferSurface != NULL) {
        int fd = hwc.getAndResetReleaseFenceFd(mType);
            mFramebufferSurface->setReleaseFenceFd(fd);
        }
        mDisplaySurface->setReleaseFenceFd(fd);
    }
}

@@ -455,9 +444,7 @@ void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const {

    result.append(buffer);

    String8 fbtargetDump;
    if (mFramebufferSurface != NULL) {
        mFramebufferSurface->dump(fbtargetDump);
        result.append(fbtargetDump);
    }
    String8 surfaceDump;
    mDisplaySurface->dump(surfaceDump);
    result.append(surfaceDump);
}
+3 −6
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ struct ANativeWindow;
namespace android {

class DisplayInfo;
class FramebufferSurface;
class DisplaySurface;
class Layer;
class SurfaceFlinger;
class HWComposer;
@@ -74,8 +74,7 @@ public:
            DisplayType type,
            bool isSecure,
            const wp<IBinder>& displayToken,
            const sp<ANativeWindow>& nativeWindow,
            const sp<FramebufferSurface>& framebufferSurface,
            const sp<DisplaySurface>& displaySurface,
            EGLConfig config);

    ~DisplayDevice();
@@ -165,9 +164,7 @@ private:

    // ANativeWindow this display is rendering into
    sp<ANativeWindow> mNativeWindow;

    // set if mNativeWindow is a FramebufferSurface
    sp<FramebufferSurface> mFramebufferSurface;
    sp<DisplaySurface> mDisplaySurface;

    EGLDisplay      mDisplay;
    EGLSurface      mSurface;
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright 2013 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_DISPLAY_SURFACE_H
#define ANDROID_SF_DISPLAY_SURFACE_H

#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>

// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------

class IGraphicBufferProducer;
class String8;

class DisplaySurface : public virtual RefBase {
public:
    virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;

    // Should be called when composition rendering is complete for a frame (but
    // eglSwapBuffers hasn't necessarily been called). Required by certain
    // older drivers for synchronization.
    // TODO: Remove this when we drop support for HWC 1.0.
    virtual status_t compositionComplete() = 0;

    // Inform the surface that GLES composition is complete for this frame, and
    // the surface should make sure that HWComposer has the correct buffer for
    // this frame. Some implementations may only push a new buffer to
    // HWComposer if GLES composition took place, others need to push a new
    // buffer on every frame.
    virtual status_t advanceFrame() = 0;

    // setReleaseFenceFd stores a fence file descriptor that will signal when
    // the current buffer is no longer being read. This fence will be returned
    // to the producer when the current buffer is released by updateTexImage().
    // Multiple fences can be set for a given buffer; they will be merged into
    // a single union fence. The GLConsumer will close the file descriptor
    // when finished with it.
    virtual status_t setReleaseFenceFd(int fenceFd) = 0;

    virtual void dump(String8& result) const = 0;

protected:
    DisplaySurface() {}
    virtual ~DisplaySurface() {}
};

// ---------------------------------------------------------------------------
} // namespace android
// ---------------------------------------------------------------------------

#endif // ANDROID_SF_DISPLAY_SURFACE_H
+28 −1
Original line number Diff line number Diff line
@@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}

sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const {
    return getBufferQueue();
}

status_t FramebufferSurface::advanceFrame() {
    // Once we remove FB HAL support, we can call nextBuffer() from here
    // instead of using onFrameAvailable(). No real benefit, except it'll be
    // more like VirtualDisplaySurface.
    return NO_ERROR;
}

status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
    Mutex::Autolock lock(mMutex);

@@ -147,7 +158,23 @@ status_t FramebufferSurface::compositionComplete()
    return mHwc.fbCompositionComplete();
}

void FramebufferSurface::dump(String8& result) {
// Since DisplaySurface and ConsumerBase both have a method with this
// signature, results will vary based on the static pointer type the caller is
// using:
//   void dump(FrameBufferSurface* fbs, String8& s) {
//       // calls FramebufferSurface::dump()
//       fbs->dump(s);
//
//       // calls ConsumerBase::dump() since it is non-virtual
//       static_cast<ConsumerBase*>(fbs)->dump(s);
//
//       // calls FramebufferSurface::dump() since it is virtual
//       static_cast<DisplaySurface*>(fbs)->dump(s);
//   }
// To make sure that all of these end up doing the same thing, we just redirect
// to ConsumerBase::dump() here. It will take the internal lock, and then call
// virtual dumpLocked(), which is where the real work happens.
void FramebufferSurface::dump(String8& result) const {
    ConsumerBase::dump(result);
}

Loading