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

Commit 694d4996 authored by sergeyv's avatar sergeyv
Browse files

Routine to upload hardware bitmaps

Change-Id: Id8283a0975325e6830d55fd1e33c5f292a1e9be0
Test: refactoring cl.
bug:30999911
parent 2a38c42e
Loading
Loading
Loading
Loading
+43 −18
Original line number Diff line number Diff line
@@ -82,6 +82,12 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for
void Texture::deleteTexture() {
    mCaches.textureState().deleteTexture(mId);
    mId = 0;
    mTarget = GL_NONE;
    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
        EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
        mEglImageHandle = EGL_NO_IMAGE_KHR;
    }
}

bool Texture::updateSize(uint32_t width, uint32_t height, GLint internalFormat,
@@ -129,6 +135,17 @@ void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height,
    GL_CHECKPOINT(MODERATE);
}

void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
    EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
        mEglImageHandle = EGL_NO_IMAGE_KHR;
    }
    mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
            buffer->getNativeBuffer(), 0);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
}

static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
        GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height, const GLvoid * data) {

@@ -173,7 +190,7 @@ static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GL
    }
}

static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
        bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
    switch (colorType) {
    case kAlpha_8_SkColorType:
@@ -214,6 +231,24 @@ static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorTy
    }
}

SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB) {
    SkBitmap rgbaBitmap;
    rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
            bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
    rgbaBitmap.eraseColor(0);
    SkCanvas canvas(rgbaBitmap);
    canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
    return rgbaBitmap;
}

bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB) {
    bool needSRGB = info.colorSpace() == sRGB;
    return info.colorType() == kARGB_4444_SkColorType
        || info.colorType() == kIndex_8_SkColorType
        || (info.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB);
}


void Texture::upload(Bitmap& bitmap) {
    if (!bitmap.readyToDraw()) {
        ALOGE("Cannot generate texture from bitmap");
@@ -243,33 +278,23 @@ void Texture::upload(Bitmap& bitmap) {
    GLint internalFormat, format, type;
    colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB, &internalFormat, &format, &type);

    if (updateSize(bitmap.width(), bitmap.height(), internalFormat, format, GL_TEXTURE_2D)) {
        needsAlloc = true;
    }
    GLenum target = bitmap.isHardware() ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
    needsAlloc |= updateSize(bitmap.width(), bitmap.height(), internalFormat, format, target);

    blend = !bitmap.isOpaque();
    mCaches.textureState().bindTexture(mId);
    mCaches.textureState().bindTexture(mTarget, mId);

    // TODO: Handle sRGB gray bitmaps
    bool hasSRGB = mCaches.extensions().hasSRGB();
    if (CC_UNLIKELY(bitmap.colorType() == kARGB_4444_SkColorType
            || bitmap.colorType() == kIndex_8_SkColorType
            || (bitmap.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB))) {

        SkBitmap rgbaBitmap;
        rgbaBitmap.allocPixels(SkImageInfo::MakeN32(
                mWidth, mHeight, bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
        rgbaBitmap.eraseColor(0);

        SkCanvas canvas(rgbaBitmap);
    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasSRGB, sRGB.get()))) {
        SkBitmap skBitmap;
        bitmap.getSkBitmap(&skBitmap);
        canvas.drawBitmap(skBitmap, 0.0f, 0.0f, nullptr);

        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
        uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
                rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
                rgbaBitmap.height(), rgbaBitmap.getPixels());

    } else if (bitmap.isHardware()) {
        uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
    } else {
        uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
                bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.pixels());
+13 −1
Original line number Diff line number Diff line
@@ -21,8 +21,14 @@
#include "hwui/Bitmap.h"

#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <SkBitmap.h>

namespace android {

class GraphicBuffer;

namespace uirenderer {

class Caches;
@@ -34,6 +40,11 @@ class Layer;
 */
class Texture : public GpuMemoryTracker {
public:
    static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB);
    static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB);
    static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
            bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType);

    explicit Texture(Caches& caches)
        : GpuMemoryTracker(GpuObjectType::Texture)
        , mCaches(caches)
@@ -147,7 +158,6 @@ public:
     * the current frame. This is reset at the start of a new frame.
     */
    void* isInUse = nullptr;

private:
    // TODO: Temporarily grant private access to Layer, remove once
    // Layer can be de-tangled from being a dual-purpose render target
@@ -157,6 +167,7 @@ private:
    // Returns true if the size changed, false if it was the same
    bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
            GLint format, GLenum target);
    void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
    void resetCachedParams();

    GLuint mId = 0;
@@ -165,6 +176,7 @@ private:
    GLint mFormat = 0;
    GLint mInternalFormat = 0;
    GLenum mTarget = GL_NONE;
    EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;

    /* See GLES spec section 3.8.14
     * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
+208 −0
Original line number Diff line number Diff line
@@ -16,11 +16,27 @@
#include "Bitmap.h"

#include "Caches.h"
#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"

#include <cutils/log.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>


#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
#include <binder/IServiceManager.h>
#include <ui/PixelFormat.h>

#include <SkCanvas.h>

namespace android {

static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
@@ -76,6 +92,167 @@ static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& info, si
    return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, ctable));
}

#define FENCE_TIMEOUT 2000000000

// TODO: handle SRGB sanely
static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
    switch (internalFormat) {
    case GL_ALPHA:
        return PIXEL_FORMAT_TRANSPARENT;
    case GL_LUMINANCE:
        return PIXEL_FORMAT_RGBA_8888;
    case GL_SRGB8_ALPHA8:
        return PIXEL_FORMAT_RGBA_8888;
    case GL_RGBA:
        return PIXEL_FORMAT_RGBA_8888;
    default:
        LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
        return PIXEL_FORMAT_UNKNOWN;
    }
}

class AutoEglFence {
public:
    AutoEglFence(EGLDisplay display)
            : mDisplay(display) {
        fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
    }

    ~AutoEglFence() {
        if (fence != EGL_NO_SYNC_KHR) {
            eglDestroySyncKHR(mDisplay, fence);
        }
    }

    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
private:
    EGLDisplay mDisplay = EGL_NO_DISPLAY;
};

class AutoEglImage {
public:
    AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
            : mDisplay(display) {
        EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
        image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
                EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
    }

    ~AutoEglImage() {
        if (image != EGL_NO_IMAGE_KHR) {
            eglDestroyImageKHR(mDisplay, image);
        }
    }

    EGLImageKHR image = EGL_NO_IMAGE_KHR;
private:
    EGLDisplay mDisplay = EGL_NO_DISPLAY;
};

static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
        GraphicBuffer& buffer, GLint format, GLint type) {
    SkAutoLockPixels alp(bitmap);
    EGLDisplay display = eglGetCurrentDisplay();
    LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
                "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
                uirenderer::renderthread::EglManager::eglErrorString());
    // These objects are initialized below but the default "null"
    // values are used to cleanup properly at any point in the
    // initialization sequenc
    GLuint texture = 0;
    // We use an EGLImage to access the content of the GraphicBuffer
    // The EGL image is later bound to a 2D texture
    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
    AutoEglImage autoImage(display, clientBuffer);
    if (autoImage.image == EGL_NO_IMAGE_KHR) {
        ALOGW("Could not create EGL image, err =%s",
                uirenderer::renderthread::EglManager::eglErrorString());
        return false;
    }
    glGenTextures(1, &texture);
    caches.textureState().bindTexture(texture);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);

    GL_CHECKPOINT(MODERATE);

    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
            format, type, bitmap.getPixels());

    GL_CHECKPOINT(MODERATE);

    // The fence is used to wait for the texture upload to finish
    // properly. We cannot rely on glFlush() and glFinish() as
    // some drivers completely ignore these API calls
    AutoEglFence autoFence(display);
    if (autoFence.fence == EGL_NO_SYNC_KHR) {
        LOG_ALWAYS_FATAL("Could not create sync fence %#x", eglGetError());
        return false;
    }
    // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
    // pipeline flush (similar to what a glFlush() would do.)
    EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
            EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
    if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
        LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
        return false;
    }
    return true;
}

sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(uirenderer::renderthread::RenderThread& renderThread,
        SkBitmap& skBitmap) {
    renderThread.eglManager().initialize();
    uirenderer::Caches& caches = uirenderer::Caches::getInstance();

    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
    if (alloc == NULL) {
        ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
        return nullptr;
    }

    const SkImageInfo& info = skBitmap.info();
    if (info.colorType() == kUnknown_SkColorType) {
        ALOGW("unable to create hardware bitmap of configuration");
        return nullptr;
    }

    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
    bool needSRGB = skBitmap.info().colorSpace() == sRGB.get();
    bool hasSRGB = caches.extensions().hasSRGB();
    GLint format, type, internalFormat;
    uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
            needSRGB, &internalFormat, &format, &type);

    PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
    status_t error;
    sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(info.width(), info.height(), pixelFormat,
            GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER
            | GraphicBuffer::USAGE_SW_READ_NEVER , &error);

    if (!buffer.get()) {
        ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
        return nullptr;
    }

    SkBitmap bitmap;
    if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
            hasSRGB, sRGB.get()))) {
        bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
    } else {
        bitmap = skBitmap;
    }

    if (!uploadBitmapToGraphicBuffer(caches, bitmap, *buffer, format, type)) {
        return nullptr;
    }
    return sk_sp<Bitmap>(new Bitmap(std::move(buffer), info));
}

sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(SkBitmap& bitmap) {
    return uirenderer::renderthread::RenderProxy::allocateHardwareBitmap(bitmap);
}

sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
   return allocateBitmap(bitmap, ctable, &android::allocateHeapBitmap);
}
@@ -183,6 +360,16 @@ Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
    reconfigure(info, rowBytes, ctable);
}

Bitmap::Bitmap(sp<GraphicBuffer>&& buffer, const SkImageInfo& info)
        : SkPixelRef(info)
        , mPixelStorageType(PixelStorageType::Hardware) {
    auto rawBuffer = buffer.get();
    mPixelStorage.hardware.buffer = rawBuffer;
    if (rawBuffer) {
        rawBuffer->incStrong(rawBuffer);
    }
    mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
}
Bitmap::~Bitmap() {
    switch (mPixelStorageType) {
    case PixelStorageType::External:
@@ -196,6 +383,12 @@ Bitmap::~Bitmap() {
    case PixelStorageType::Heap:
        free(mPixelStorage.heap.address);
        break;
    case PixelStorageType::Hardware:
        auto buffer = mPixelStorage.hardware.buffer;
        buffer->decStrong(buffer);
        mPixelStorage.hardware.buffer = nullptr;
        break;

    }

    if (android::uirenderer::Caches::hasInstance()) {
@@ -219,6 +412,9 @@ void* Bitmap::getStorage() const {
        return mPixelStorage.ashmem.address;
    case PixelStorageType::Heap:
        return mPixelStorage.heap.address;
    case PixelStorageType::Hardware:
        LOG_ALWAYS_FATAL_IF("Can't get address for hardware bitmap");
        return nullptr;
    }
}

@@ -264,6 +460,11 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) {
}

void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
    if (isHardware()) {
        //TODO: use readback to get pixels
        LOG_ALWAYS_FATAL("Not implemented");
        return;
    }
    outBitmap->setInfo(info(), rowBytes());
    outBitmap->setPixelRef(this);
    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
@@ -274,4 +475,11 @@ void Bitmap::getBounds(SkRect* bounds) const {
    bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));
}

GraphicBuffer* Bitmap::graphicBuffer() {
    if (isHardware()) {
        return mPixelStorage.hardware.buffer;
    }
    return nullptr;
}

} // namespace android
 No newline at end of file
+26 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <SkImageInfo.h>
#include <SkPixelRef.h>
#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>

namespace android {

@@ -27,8 +28,17 @@ enum class PixelStorageType {
    External,
    Heap,
    Ashmem,
    Hardware,
};

namespace uirenderer {
namespace renderthread {
    class RenderThread;
}
}

class PixelStorage;

typedef void (*FreeFunc)(void* addr, void* context);

class ANDROID_API Bitmap : public SkPixelRef {
@@ -36,17 +46,24 @@ public:
    static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable);
    static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info);

    static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);

    static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable);
    static sk_sp<Bitmap> allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info,
        size_t rowBytes, SkColorTable* ctable);

    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);

    static sk_sp<Bitmap> allocateHardwareBitmap(uirenderer::renderthread::RenderThread&,
            SkBitmap& bitmap);

    Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
            SkColorTable* ctable);
    Bitmap(void* address, void* context, FreeFunc freeFunc,
            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
    Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
            size_t rowBytes, SkColorTable* ctable);
    Bitmap(sp<GraphicBuffer>&& buffer, const SkImageInfo& info);

    int width() const { return info().width(); }
    int height() const { return info().height(); }
@@ -81,13 +98,18 @@ public:
    bool readyToDraw() const {
        return this->colorType() != kIndex_8_SkColorType || mColorTable;
    }

    bool isHardware() const {
        return mPixelStorageType == PixelStorageType::Hardware;
    }

    GraphicBuffer* graphicBuffer();
protected:
    virtual bool onNewLockPixels(LockRec* rec) override;
    virtual void onUnlockPixels() override { };
    virtual size_t getAllocatedSizeInBytes() const override;
private:
    virtual ~Bitmap();
    void doFreePixels();
    void* getStorage() const;

    PixelStorageType mPixelStorageType;
@@ -111,6 +133,9 @@ private:
            void* address;
            size_t size;
        } heap;
        struct {
            GraphicBuffer* buffer;
        } hardware;
    } mPixelStorage;
};

+13 −12
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "EglManager.h"

#include "Texture.h"
#include "Caches.h"
#include "DeviceInfo.h"
#include "Properties.h"
@@ -58,7 +59,7 @@ static const char* egl_error_str(EGLint error) {
        return "Unknown error";
    }
}
static const char* egl_error_str() {
const char* EglManager::eglErrorString() {
    return egl_error_str(eglGetError());
}

@@ -101,11 +102,11 @@ void EglManager::initialize() {

    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", eglErrorString());

    EGLint major, minor;
    LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
            "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
            "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());

    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);

@@ -173,7 +174,7 @@ void EglManager::loadConfig() {
            loadConfig();
        } else {
            // Failed to get a valid config
            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
        }
    }
}
@@ -185,7 +186,7 @@ void EglManager::createContext() {
    };
    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
    LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
        "Failed to create context, error = %s", egl_error_str());
        "Failed to create context, error = %s", eglErrorString());
}

void EglManager::createPBufferSurface() {
@@ -212,12 +213,12 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, attribs);
    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
            "Failed to create EGLSurface for window %p, eglErr = %s",
            (void*) window, egl_error_str());
            (void*) window, eglErrorString());

    if (mSwapBehavior != SwapBehavior::Preserved) {
        LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE,
                            "Failed to set swap behavior to destroyed for window %p, eglErr = %s",
                            (void*) window, egl_error_str());
                            (void*) window, eglErrorString());
    }

    return surface;
@@ -228,7 +229,7 @@ void EglManager::destroySurface(EGLSurface surface) {
        makeCurrent(EGL_NO_SURFACE);
    }
    if (!eglDestroySurface(mEglDisplay, surface)) {
        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, eglErrorString());
    }
}

@@ -262,7 +263,7 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
                    (void*)surface, egl_error_str(*errOut));
        } else {
            LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
                    (void*)surface, egl_error_str());
                    (void*)surface, eglErrorString());
        }
    }
    mCurrentSurface = surface;
@@ -303,7 +304,7 @@ void EglManager::damageFrame(const Frame& frame, const SkRect& dirty) {
        frame.map(dirty, rects);
        if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) {
            LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s",
                    (void*)frame.mSurface, egl_error_str());
                    (void*)frame.mSurface, eglErrorString());
        }
    }
#endif
@@ -357,14 +358,14 @@ bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
            preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
    if (!preserved) {
        ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
                (void*) surface, egl_error_str());
                (void*) surface, eglErrorString());
        // Maybe it's already set?
        EGLint swapBehavior;
        if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
            preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
        } else {
            ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
                                (void*) surface, egl_error_str());
                                (void*) surface, eglErrorString());
        }
    }

Loading