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

Commit 578492e9 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "changes to SurfaceTexture needed for unification with SF"

parents 4af51a14 27cd07ca
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -127,11 +127,28 @@ public:
    // be called from the client.
    status_t setDefaultBufferSize(uint32_t w, uint32_t h);

private:
    // getCurrentBuffer returns the buffer associated with the current image.
    sp<GraphicBuffer> getCurrentBuffer() const;

    // getCurrentTextureTarget returns the texture target of the current
    // texture as returned by updateTexImage().
    GLenum getCurrentTextureTarget() const;

    // getCurrentCrop returns the cropping rectangle of the current buffer
    Rect getCurrentCrop() const;

    // getCurrentTransform returns the transform of the current buffer
    uint32_t getCurrentTransform() const;

protected:

    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
    // all slots.
    void freeAllBuffers();
    static bool isExternalFormat(uint32_t format);
    static GLenum getTextureTarget(uint32_t format);

private:

    // createImage creates a new EGLImage from a GraphicBuffer.
    EGLImageKHR createImage(EGLDisplay dpy,
@@ -194,6 +211,10 @@ private:
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    int mCurrentTexture;

    // mCurrentTextureTarget is the GLES texture target to be used with the
    // current texture.
    GLenum mCurrentTextureTarget;

    // mCurrentTextureBuf is the graphic buffer of the current texture. It's
    // possible that this buffer is not associated with any buffer slot, so we
    // must track it separately in order to properly use
@@ -256,7 +277,7 @@ private:
    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of SurfaceTexture objects. It must be locked whenever the
    // member variables are accessed.
    Mutex mMutex;
    mutable Mutex mMutex;
};

// ----------------------------------------------------------------------------
+21 −1
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

namespace android {

class Surface;

class SurfaceTextureClient
    : public EGLNativeBase<ANativeWindow, SurfaceTextureClient, RefBase>
{
@@ -36,6 +38,7 @@ public:
    sp<ISurfaceTexture> getISurfaceTexture() const;

private:
    friend class Surface;

    // can't be copied
    SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs);
@@ -78,6 +81,8 @@ private:

    void freeAllBuffers();

    int getConnectedApi() const;

    enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS };
    enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS };
    enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
@@ -121,10 +126,25 @@ private:
    // a timestamp is auto-generated when queueBuffer is called.
    int64_t mTimestamp;

    // mConnectedApi holds the currently connected API to this surface
    int mConnectedApi;

    // mQueryWidth is the width returned by query(). It is set to width
    // of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
    uint32_t mQueryWidth;

    // mQueryHeight is the height returned by query(). It is set to height
    // of the last dequeued buffer or to mReqHeight if no buffer was dequeued.
    uint32_t mQueryHeight;

    // mQueryFormat is the format returned by query(). It is set to the last
    // dequeued format or to mReqFormat if no buffer was dequeued.
    uint32_t mQueryFormat;

    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of SurfaceTexture objects. It must be locked whenever the
    // member variables are accessed.
    Mutex mMutex;
    mutable Mutex mMutex;
};

}; // namespace android
+68 −4
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@

#include <gui/SurfaceTexture.h>

#include <hardware/hardware.h>

#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/IGraphicBufferAlloc.h>
@@ -82,6 +84,7 @@ SurfaceTexture::SurfaceTexture(GLuint tex) :
    mUseDefaultSize(true),
    mBufferCount(MIN_BUFFER_SLOTS),
    mCurrentTexture(INVALID_BUFFER_SLOT),
    mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
    mCurrentTransform(0),
    mCurrentTimestamp(0),
    mLastQueued(INVALID_BUFFER_SLOT),
@@ -197,6 +200,7 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) {
    if (buffer == NULL) {
        return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    }

    if ((mUseDefaultSize) &&
        ((uint32_t(buffer->width) != mDefaultWidth) ||
         (uint32_t(buffer->height) != mDefaultHeight))) {
@@ -263,9 +267,6 @@ status_t SurfaceTexture::updateTexImage() {
    LOGV("SurfaceTexture::updateTexImage");
    Mutex::Autolock lock(mMutex);

    // We always bind the texture even if we don't update its contents.
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);

    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
    // so this check will fail until a buffer gets queued.
    if (mCurrentTexture != mLastQueued) {
@@ -283,7 +284,15 @@ status_t SurfaceTexture::updateTexImage() {
        while ((error = glGetError()) != GL_NO_ERROR) {
            LOGE("GL error cleared before updating SurfaceTexture: %#04x", error);
        }
        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);

        GLenum target = getTextureTarget(
                mSlots[mLastQueued].mGraphicBuffer->format);
        if (target != mCurrentTextureTarget) {
            glDeleteTextures(1, &mTexName);
        }
        glBindTexture(target, mTexName);
        glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);

        bool failed = false;
        while ((error = glGetError()) != GL_NO_ERROR) {
            LOGE("error binding external texture image %p (slot %d): %#04x",
@@ -296,14 +305,53 @@ status_t SurfaceTexture::updateTexImage() {

        // Update the SurfaceTexture state.
        mCurrentTexture = mLastQueued;
        mCurrentTextureTarget = target;
        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
        mCurrentCrop = mLastQueuedCrop;
        mCurrentTransform = mLastQueuedTransform;
        mCurrentTimestamp = mLastQueuedTimestamp;
    } else {
        // We always bind the texture even if we don't update its contents.
        glBindTexture(mCurrentTextureTarget, mTexName);
    }
    return OK;
}

bool SurfaceTexture::isExternalFormat(uint32_t format)
{
    switch (format) {
    // supported YUV formats
    case HAL_PIXEL_FORMAT_YV12:
    // Legacy/deprecated YUV formats
    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    case HAL_PIXEL_FORMAT_YCbCr_422_I:
        return true;
    }

    // Any OEM format needs to be considered
    if (format>=0x100 && format<=0x1FF)
        return true;

    return false;
}

GLenum SurfaceTexture::getTextureTarget(uint32_t format)
{
    GLenum target = GL_TEXTURE_2D;
#if defined(GL_OES_EGL_image_external)
    if (isExternalFormat(format)) {
        target = GL_TEXTURE_EXTERNAL_OES;
    }
#endif
    return target;
}

GLenum SurfaceTexture::getCurrentTextureTarget() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentTextureTarget;
}

void SurfaceTexture::getTransformMatrix(float mtx[16]) {
    LOGV("SurfaceTexture::getTransformMatrix");
    Mutex::Autolock lock(mMutex);
@@ -445,6 +493,22 @@ EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
    return image;
}

sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentTextureBuf;
}

Rect SurfaceTexture::getCurrentCrop() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentCrop;
}

uint32_t SurfaceTexture::getCurrentTransform() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentTransform;
}


static void mtxMul(float out[16], const float a[16], const float b[16]) {
    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
+52 −13
Original line number Diff line number Diff line
@@ -26,8 +26,10 @@ namespace android {
SurfaceTextureClient::SurfaceTextureClient(
        const sp<ISurfaceTexture>& surfaceTexture):
        mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
        mReqHeight(0), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() {
        mReqHeight(0), mReqFormat(0), mReqUsage(0),
        mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mConnectedApi(0),
        mQueryWidth(0), mQueryHeight(0), mQueryFormat(0),
        mMutex() {
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = setSwapInterval;
    ANativeWindow::dequeueBuffer    = dequeueBuffer;
@@ -101,9 +103,10 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
    }
    sp<GraphicBuffer>& gbuf(mSlots[buf]);
    if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION ||
        gbuf == 0 || gbuf->getWidth() != mReqWidth ||
        gbuf->getHeight() != mReqHeight ||
        uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
        gbuf == 0 ||
        (mReqWidth && gbuf->getWidth() != mReqWidth) ||
        (mReqHeight && gbuf->getHeight() != mReqHeight) ||
        (mReqFormat && uint32_t(gbuf->getPixelFormat()) != mReqFormat) ||
        (gbuf->getUsage() & mReqUsage) != mReqUsage) {
        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
                mReqFormat, mReqUsage);
@@ -111,6 +114,9 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
            return NO_MEMORY;
        }
        mQueryWidth  = gbuf->width;
        mQueryHeight = gbuf->height;
        mQueryFormat = gbuf->format;
    }
    *buffer = gbuf.get();
    return OK;
@@ -159,13 +165,13 @@ int SurfaceTextureClient::query(int what, int* value) {
    Mutex::Autolock lock(mMutex);
    switch (what) {
    case NATIVE_WINDOW_WIDTH:
        *value = mQueryWidth ? mQueryWidth : mReqWidth;
        return NO_ERROR;
    case NATIVE_WINDOW_HEIGHT:
        // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't
        // override the size?
        *value = 0;
        *value = mQueryHeight ? mQueryHeight : mReqHeight;
        return NO_ERROR;
    case NATIVE_WINDOW_FORMAT:
        *value = DEFAULT_FORMAT;
        *value = mQueryFormat ? mQueryFormat : mReqFormat;
        return NO_ERROR;
    case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
        *value = MIN_UNDEQUEUED_BUFFERS;
@@ -260,16 +266,49 @@ int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {

int SurfaceTextureClient::connect(int api) {
    LOGV("SurfaceTextureClient::connect");
    // XXX: Implement this!
    return INVALID_OPERATION;
    Mutex::Autolock lock(mMutex);
    int err = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
            if (mConnectedApi) {
                err = -EINVAL;
            } else {
                mConnectedApi = api;
            }
            break;
        default:
            err = -EINVAL;
            break;
    }
    return err;
}

int SurfaceTextureClient::disconnect(int api) {
    LOGV("SurfaceTextureClient::disconnect");
    // XXX: Implement this!
    return INVALID_OPERATION;
    Mutex::Autolock lock(mMutex);
    int err = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
            if (mConnectedApi == api) {
                mConnectedApi = 0;
            } else {
                err = -EINVAL;
            }
            break;
        default:
            err = -EINVAL;
            break;
    }
    return err;
}

int SurfaceTextureClient::getConnectedApi() const
{
    Mutex::Autolock lock(mMutex);
    return mConnectedApi;
}


int SurfaceTextureClient::setUsage(uint32_t reqUsage)
{
    LOGV("SurfaceTextureClient::setUsage");