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 Diff line number Diff line
@@ -26,12 +26,15 @@
#include <ui/GraphicBuffer.h>

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

#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"

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

class IGraphicBufferAlloc;

class SurfaceTexture : public BnSurfaceTexture {
public:
    enum { MIN_BUFFER_SLOTS = 3 };
@@ -140,6 +143,12 @@ private:
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    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.
    // It gets set to mLastQueuedCrop each time updateTexImage is called.
    Rect mCurrentCrop;
@@ -176,6 +185,16 @@ private:
    // changed with a call to setTexName.
    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
    // variables of SurfaceTexture objects. It must be locked whenever the
    // member variables are accessed.
+64 −0
Original line number 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 Diff line number Diff line
@@ -28,6 +28,7 @@
#include <ui/PixelFormat.h>

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

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

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

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

@@ -131,13 +136,6 @@ public:
     * This is an ASYNCHRONOUS call.
     */
    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,
        CREATE_CONNECTION,
        CREATE_CLIENT_CONNECTION,
        CREATE_GRAPHIC_BUFFER,
        CREATE_GRAPHIC_BUFFER_ALLOC,
        GET_CBLK,
        OPEN_GLOBAL_TRANSACTION,
        CLOSE_GLOBAL_TRANSACTION,
+30 −13
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

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

#include <utils/Log.h>

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

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

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

        // Update the SurfaceTexture state.
        mCurrentTexture = mLastQueued;
        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
        mCurrentCrop = mLastQueuedCrop;
        mCurrentTransform = mLastQueuedTransform;
    }
    return OK;
}
@@ -282,6 +286,19 @@ void SurfaceTexture::freeAllBuffers() {
            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,
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
	ISurfaceComposer.cpp \
	ISurface.cpp \
	ISurfaceComposerClient.cpp \
	IGraphicBufferAlloc.cpp \
	LayerState.cpp \
	SharedBufferStack.cpp \
	Surface.cpp \
Loading