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

Commit 97cc85fd authored by Sergei Vasilinetc's avatar Sergei Vasilinetc Committed by Android (Google) Code Review
Browse files

Merge "Routine to upload hardware bitmaps"

parents b236e8dd 694d4996
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"
@@ -60,7 +61,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());
}

@@ -103,11 +104,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);

@@ -186,7 +187,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());
        }
    }
}
@@ -198,7 +199,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() {
@@ -225,12 +226,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;
@@ -241,7 +242,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());
    }
}

@@ -276,7 +277,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;
@@ -317,7 +318,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
@@ -371,14 +372,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