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

Commit b5dc8004 authored by Jamie Gennis's avatar Jamie Gennis Committed by Android (Google) Code Review
Browse files

Merge "Fix remote GraphicBuffer allocation in SurfaceFlinger." into honeycomb

parents c16387eb 9a78c90c
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -26,12 +26,15 @@
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBuffer.h>


#include <utils/threads.h>
#include <utils/threads.h>
#include <utils/Vector.h>


#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"


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


class IGraphicBufferAlloc;

class SurfaceTexture : public BnSurfaceTexture {
class SurfaceTexture : public BnSurfaceTexture {
public:
public:
    enum { MIN_BUFFER_SLOTS = 3 };
    enum { MIN_BUFFER_SLOTS = 3 };
@@ -140,6 +143,12 @@ private:
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    int mCurrentTexture;
    int mCurrentTexture;


    // 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
    // IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
    sp<GraphicBuffer> mCurrentTextureBuf;

    // mCurrentCrop is the crop rectangle that applies to the current texture.
    // mCurrentCrop is the crop rectangle that applies to the current texture.
    // It gets set to mLastQueuedCrop each time updateTexImage is called.
    // It gets set to mLastQueuedCrop each time updateTexImage is called.
    Rect mCurrentCrop;
    Rect mCurrentCrop;
@@ -176,6 +185,16 @@ private:
    // changed with a call to setTexName.
    // changed with a call to setTexName.
    const GLuint mTexName;
    const GLuint mTexName;


    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
    // allocate new GraphicBuffer objects.
    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;

    // mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is
    // referencing. This is kept so that gralloc implementations do not need to
    // properly handle the case where SurfaceFlinger no longer holds a reference
    // to a buffer, but other processes do.
    Vector<sp<GraphicBuffer> > mAllocdBuffers;

    // mMutex is the mutex used to prevent concurrent access to the member
    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of SurfaceTexture objects. It must be locked whenever the
    // variables of SurfaceTexture objects. It must be locked whenever the
    // member variables are accessed.
    // member variables are accessed.
+64 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2011 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_IGRAPHIC_BUFFER_ALLOC_H
#define ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/RefBase.h>

#include <binder/IInterface.h>

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

class IGraphicBufferAlloc : public IInterface
{
public:
    DECLARE_META_INTERFACE(GraphicBufferAlloc);

    /* Create a new GraphicBuffer for the client to use.  The server will
     * maintain a reference to the newly created GraphicBuffer until
     * freeAllGraphicBuffers is called.
     */
    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
            PixelFormat format, uint32_t usage) = 0;

    /* Free all but one of the GraphicBuffer objects that the server is
     * currently referencing. If bufIndex is not a valid index of the buffers
     * the server is referencing, then all buffers are freed.
     */
    virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0;
};

// ----------------------------------------------------------------------------

class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

// ----------------------------------------------------------------------------

}; // namespace android

#endif // ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
+6 −8
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include <ui/PixelFormat.h>
#include <ui/PixelFormat.h>


#include <surfaceflinger/ISurfaceComposerClient.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
#include <surfaceflinger/IGraphicBufferAlloc.h>


namespace android {
namespace android {
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -96,6 +97,10 @@ public:
     */
     */
    virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
    virtual sp<ISurfaceComposerClient> createClientConnection() = 0;


    /* create a graphic buffer allocator
     */
    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;

    /* retrieve the control block */
    /* retrieve the control block */
    virtual sp<IMemoryHeap> getCblk() const = 0;
    virtual sp<IMemoryHeap> getCblk() const = 0;


@@ -131,13 +136,6 @@ public:
     * This is an ASYNCHRONOUS call.
     * This is an ASYNCHRONOUS call.
     */
     */
    virtual void signal() const = 0;
    virtual void signal() const = 0;

    /* Create a new GraphicBuffer for the client to use.  SurfaceFlinger will
     * not maintain a reference to the GraphicBuffer, so the underlying native
     * handle will be freed once the client references are released.
     */
    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
            PixelFormat format, uint32_t usage) const = 0;
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -151,7 +149,7 @@ public:
        BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
        BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
        CREATE_CONNECTION,
        CREATE_CONNECTION,
        CREATE_CLIENT_CONNECTION,
        CREATE_CLIENT_CONNECTION,
        CREATE_GRAPHIC_BUFFER,
        CREATE_GRAPHIC_BUFFER_ALLOC,
        GET_CBLK,
        GET_CBLK,
        OPEN_GLOBAL_TRANSACTION,
        OPEN_GLOBAL_TRANSACTION,
        CLOSE_GLOBAL_TRANSACTION,
        CLOSE_GLOBAL_TRANSACTION,
+30 −13
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@


#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/IGraphicBufferAlloc.h>


#include <utils/Log.h>
#include <utils/Log.h>


@@ -83,6 +84,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex) :
        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
        mSlots[i].mOwnedByClient = false;
        mSlots[i].mOwnedByClient = false;
    }
    }
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
}
}


SurfaceTexture::~SurfaceTexture() {
SurfaceTexture::~SurfaceTexture() {
@@ -110,9 +113,8 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
        return 0;
        return 0;
    }
    }
    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    sp<GraphicBuffer> graphicBuffer(
    sp<GraphicBuffer> graphicBuffer(composer->createGraphicBuffer(w, h,
            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
            format, usage));
    if (graphicBuffer == 0) {
    if (graphicBuffer == 0) {
        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
    } else {
    } else {
@@ -122,6 +124,7 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
        }
        }
        mAllocdBuffers.add(graphicBuffer);
    }
    }
    return graphicBuffer;
    return graphicBuffer;
}
}
@@ -204,27 +207,28 @@ status_t SurfaceTexture::updateTexImage() {
    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
    // so this check will fail until a buffer gets queued.
    // so this check will fail until a buffer gets queued.
    if (mCurrentTexture != mLastQueued) {
    if (mCurrentTexture != mLastQueued) {
        // Update the SurfaceTexture state.
        mCurrentTexture = mLastQueued;
        mCurrentCrop = mLastQueuedCrop;
        mCurrentTransform = mLastQueuedTransform;

        // Update the GL texture object.
        // Update the GL texture object.
        EGLImageKHR image = mSlots[mCurrentTexture].mEglImage;
        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
        if (image == EGL_NO_IMAGE_KHR) {
        if (image == EGL_NO_IMAGE_KHR) {
            EGLDisplay dpy = eglGetCurrentDisplay();
            EGLDisplay dpy = eglGetCurrentDisplay();
            sp<GraphicBuffer> graphicBuffer = mSlots[mCurrentTexture].mGraphicBuffer;
            sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
            image = createImage(dpy, graphicBuffer);
            image = createImage(dpy, graphicBuffer);
            mSlots[mCurrentTexture].mEglImage = image;
            mSlots[mLastQueued].mEglImage = image;
            mSlots[mCurrentTexture].mEglDisplay = dpy;
            mSlots[mLastQueued].mEglDisplay = dpy;
        }
        }
        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
        GLint error = glGetError();
        GLint error = glGetError();
        if (error != GL_NO_ERROR) {
        if (error != GL_NO_ERROR) {
            LOGE("error binding external texture image %p (slot %d): %#04x",
            LOGE("error binding external texture image %p (slot %d): %#04x",
                    image, mCurrentTexture, error);
                    image, mLastQueued, error);
            return -EINVAL;
            return -EINVAL;
        }
        }

        // Update the SurfaceTexture state.
        mCurrentTexture = mLastQueued;
        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
        mCurrentCrop = mLastQueuedCrop;
        mCurrentTransform = mLastQueuedTransform;
    }
    }
    return OK;
    return OK;
}
}
@@ -282,6 +286,19 @@ void SurfaceTexture::freeAllBuffers() {
            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
        }
        }
    }
    }

    int exceptBuf = -1;
    for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
        if (mAllocdBuffers[i] == mCurrentTextureBuf) {
            exceptBuf = i;
            break;
        }
    }
    mAllocdBuffers.clear();
    if (exceptBuf >= 0) {
        mAllocdBuffers.add(mCurrentTextureBuf);
    }
    mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
}
}


EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
+1 −0
Original line number Original line Diff line number Diff line
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
	ISurfaceComposer.cpp \
	ISurfaceComposer.cpp \
	ISurface.cpp \
	ISurface.cpp \
	ISurfaceComposerClient.cpp \
	ISurfaceComposerClient.cpp \
	IGraphicBufferAlloc.cpp \
	LayerState.cpp \
	LayerState.cpp \
	SharedBufferStack.cpp \
	SharedBufferStack.cpp \
	Surface.cpp \
	Surface.cpp \
Loading