diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 1745b807aba49..223b498ab0b7a 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -185,7 +185,6 @@ cc_defaults { "renderstate/TextureState.cpp", "renderthread/CacheManager.cpp", "renderthread/CanvasContext.cpp", - "renderthread/OpenGLPipeline.cpp", "renderthread/DrawFrameTask.cpp", "renderthread/EglManager.cpp", "renderthread/VulkanManager.cpp", @@ -217,7 +216,6 @@ cc_defaults { "DeferredLayerUpdater.cpp", "DeviceInfo.cpp", "DisplayList.cpp", - "Extensions.cpp", "FboCache.cpp", "FontRenderer.cpp", "FrameBuilder.cpp", @@ -236,7 +234,7 @@ cc_defaults { "LayerUpdateQueue.cpp", "Matrix.cpp", "OpDumper.cpp", - "OpenGLReadback.cpp", + "EglReadback.cpp", "Patch.cpp", "PatchCache.cpp", "PathCache.cpp", diff --git a/libs/hwui/EglReadback.cpp b/libs/hwui/EglReadback.cpp new file mode 100644 index 0000000000000..a836afe97c794 --- /dev/null +++ b/libs/hwui/EglReadback.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 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. + */ + +#include "EglReadback.h" + +#include "renderthread/EglManager.h" + +#include +#include +#include + +namespace android { +namespace uirenderer { + +CopyResult EglReadback::copySurfaceInto(Surface& surface, const Rect& srcRect, + SkBitmap* bitmap) { + ATRACE_CALL(); + // Setup the source + sp sourceBuffer; + sp sourceFence; + Matrix4 texTransform; + status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data); + texTransform.invalidateType(); + if (err != NO_ERROR) { + ALOGW("Failed to get last queued buffer, error = %d", err); + return CopyResult::UnknownError; + } + if (!sourceBuffer.get()) { + ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); + return CopyResult::SourceEmpty; + } + if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) { + ALOGW("Surface is protected, unable to copy from it"); + return CopyResult::SourceInvalid; + } + err = sourceFence->wait(500 /* ms */); + if (err != NO_ERROR) { + ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); + return CopyResult::Timeout; + } + + return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap); +} + +CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, + Matrix4& texTransform, const Rect& srcRect, + SkBitmap* bitmap) { + mRenderThread.eglManager().initialize(); + // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via + // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES + // to be able to properly sample from the buffer. + + // Create the EGLImage object that maps the GraphicBuffer + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLClientBuffer clientBuffer = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); + EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; + + EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, + clientBuffer, attrs); + + if (sourceImage == EGL_NO_IMAGE_KHR) { + ALOGW("eglCreateImageKHR failed (%#x)", eglGetError()); + return CopyResult::UnknownError; + } + + uint32_t width = graphicBuffer->getWidth(); + uint32_t height = graphicBuffer->getHeight(); + CopyResult copyResult = + copyImageInto(sourceImage, texTransform, width, height, srcRect, bitmap); + + eglDestroyImageKHR(display, sourceImage); + return copyResult; +} + +CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) { + Rect srcRect; + Matrix4 transform; + transform.loadScale(1, -1, 1); + transform.translate(0, -1); + return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap); +} + +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/OpenGLReadback.h b/libs/hwui/EglReadback.h similarity index 65% rename from libs/hwui/OpenGLReadback.h rename to libs/hwui/EglReadback.h index ca40738b49019..e723169ad795e 100644 --- a/libs/hwui/OpenGLReadback.h +++ b/libs/hwui/EglReadback.h @@ -18,16 +18,15 @@ #include "Readback.h" +#include "Matrix.h" + #include #include namespace android { namespace uirenderer { -class Matrix4; -class GlLayer; - -class OpenGLReadback : public Readback { +class EglReadback : public Readback { public: virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) override; @@ -35,8 +34,8 @@ public: SkBitmap* bitmap) override; protected: - explicit OpenGLReadback(renderthread::RenderThread& thread) : Readback(thread) {} - virtual ~OpenGLReadback() {} + explicit EglReadback(renderthread::RenderThread& thread) : Readback(thread) {} + virtual ~EglReadback() {} virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform, int imgWidth, int imgHeight, const Rect& srcRect, @@ -47,21 +46,5 @@ private: const Rect& srcRect, SkBitmap* bitmap); }; -class OpenGLReadbackImpl : public OpenGLReadback { -public: - OpenGLReadbackImpl(renderthread::RenderThread& thread) : OpenGLReadback(thread) {} - - /** - * Copies the layer's contents into the provided bitmap. - */ - static bool copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer, - SkBitmap* bitmap); - -protected: - virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform, - int imgWidth, int imgHeight, const Rect& srcRect, - SkBitmap* bitmap) override; -}; - } // namespace uirenderer } // namespace android diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp deleted file mode 100644 index 530e82e65a28f..0000000000000 --- a/libs/hwui/Extensions.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#include "Extensions.h" - -#include "Debug.h" -#include "Properties.h" -#include "utils/StringUtils.h" - -#include - -#include -#include - -#include - -namespace android { -namespace uirenderer { - -Extensions::Extensions() { - if (Properties::isSkiaEnabled()) { - return; - } - const char* version = (const char*)glGetString(GL_VERSION); - - // Section 6.1.5 of the OpenGL ES specification indicates the GL version - // string strictly follows this format: - // - // OpenGLES - // - // In addition section 6.1.5 describes the version number thusly: - // - // "The version number is either of the form major number.minor number or - // major number.minor number.release number, where the numbers all have one - // or more digits. The release number and vendor specific information are - // optional." - - if (sscanf(version, "OpenGL ES %d.%d", &mVersionMajor, &mVersionMinor) != 2) { - // If we cannot parse the version number, assume OpenGL ES 2.0 - mVersionMajor = 2; - mVersionMinor = 0; - } - - auto extensions = StringUtils::split((const char*)glGetString(GL_EXTENSIONS)); - mHasNPot = extensions.has("GL_OES_texture_npot"); - mHasFramebufferFetch = extensions.has("GL_NV_shader_framebuffer_fetch"); - mHasDiscardFramebuffer = extensions.has("GL_EXT_discard_framebuffer"); - mHasDebugMarker = extensions.has("GL_EXT_debug_marker"); - mHas1BitStencil = extensions.has("GL_OES_stencil1"); - mHas4BitStencil = extensions.has("GL_OES_stencil4"); - mHasUnpackSubImage = extensions.has("GL_EXT_unpack_subimage"); - mHasRenderableFloatTexture = extensions.has("GL_OES_texture_half_float"); - - mHasSRGB = mVersionMajor >= 3 || extensions.has("GL_EXT_sRGB"); - mHasSRGBWriteControl = extensions.has("GL_EXT_sRGB_write_control"); - -#ifdef ANDROID_ENABLE_LINEAR_BLENDING - // If linear blending is enabled, the device must have (ES3.0 or EXT_sRGB) - // and EXT_sRGB_write_control - LOG_ALWAYS_FATAL_IF(!mHasSRGB, "Linear blending requires ES 3.0 or EXT_sRGB"); - LOG_ALWAYS_FATAL_IF(!mHasSRGBWriteControl, "Linear blending requires EXT_sRGB_write_control"); - - mHasLinearBlending = true; -#else - mHasLinearBlending = false; -#endif -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 214ee0bbeefd8..e90f40c1c9794 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -26,43 +26,31 @@ namespace uirenderer { class Extensions { public: - Extensions(); + Extensions() {} - inline bool hasNPot() const { return mHasNPot; } - inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; } - inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; } - inline bool hasDebugMarker() const { return mHasDebugMarker; } - inline bool has1BitStencil() const { return mHas1BitStencil; } - inline bool has4BitStencil() const { return mHas4BitStencil; } - inline bool hasUnpackRowLength() const { return mVersionMajor >= 3 || mHasUnpackSubImage; } + inline bool hasNPot() const { return false; } + inline bool hasFramebufferFetch() const { return false; } + inline bool hasDiscardFramebuffer() const { return false; } + inline bool hasDebugMarker() const { return false; } + inline bool has1BitStencil() const { return false; } + inline bool has4BitStencil() const { return false; } + inline bool hasUnpackRowLength() const { return mVersionMajor >= 3; } inline bool hasPixelBufferObjects() const { return mVersionMajor >= 3; } inline bool hasOcclusionQueries() const { return mVersionMajor >= 3; } inline bool hasFloatTextures() const { return mVersionMajor >= 3; } inline bool hasRenderableFloatTextures() const { - return (mVersionMajor >= 3 && mVersionMinor >= 2) || mHasRenderableFloatTexture; + return (mVersionMajor >= 3 && mVersionMinor >= 2); } - inline bool hasSRGB() const { return mHasSRGB; } - inline bool hasSRGBWriteControl() const { return hasSRGB() && mHasSRGBWriteControl; } - inline bool hasLinearBlending() const { return hasSRGB() && mHasLinearBlending; } + inline bool hasSRGB() const { return false; } + inline bool hasSRGBWriteControl() const { return hasSRGB() && false; } + inline bool hasLinearBlending() const { return hasSRGB() && false; } inline int getMajorGlVersion() const { return mVersionMajor; } inline int getMinorGlVersion() const { return mVersionMinor; } private: - bool mHasNPot; - bool mHasFramebufferFetch; - bool mHasDiscardFramebuffer; - bool mHasDebugMarker; - bool mHas1BitStencil; - bool mHas4BitStencil; - bool mHasUnpackSubImage; - bool mHasSRGB; - bool mHasSRGBWriteControl; - bool mHasLinearBlending; - bool mHasRenderableFloatTexture; - - int mVersionMajor; - int mVersionMinor; + int mVersionMajor = 2; + int mVersionMinor = 0; }; // class Extensions }; // namespace uirenderer diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp deleted file mode 100644 index 11432d6296509..0000000000000 --- a/libs/hwui/OpenGLReadback.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#include "OpenGLReadback.h" - -#include "Caches.h" -#include "GlLayer.h" -#include "GlopBuilder.h" -#include "Image.h" -#include "renderstate/RenderState.h" -#include "renderthread/EglManager.h" -#include "utils/GLUtils.h" - -#include -#include -#include -#include - -namespace android { -namespace uirenderer { - -CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect, - SkBitmap* bitmap) { - ATRACE_CALL(); - // Setup the source - sp sourceBuffer; - sp sourceFence; - Matrix4 texTransform; - status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data); - texTransform.invalidateType(); - if (err != NO_ERROR) { - ALOGW("Failed to get last queued buffer, error = %d", err); - return CopyResult::UnknownError; - } - if (!sourceBuffer.get()) { - ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); - return CopyResult::SourceEmpty; - } - if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) { - ALOGW("Surface is protected, unable to copy from it"); - return CopyResult::SourceInvalid; - } - err = sourceFence->wait(500 /* ms */); - if (err != NO_ERROR) { - ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); - return CopyResult::Timeout; - } - - return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap); -} - -CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, - Matrix4& texTransform, const Rect& srcRect, - SkBitmap* bitmap) { - mRenderThread.eglManager().initialize(); - // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via - // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES - // to be able to properly sample from the buffer. - - // Create the EGLImage object that maps the GraphicBuffer - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - EGLClientBuffer clientBuffer = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); - EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; - - EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - clientBuffer, attrs); - - if (sourceImage == EGL_NO_IMAGE_KHR) { - ALOGW("eglCreateImageKHR failed (%#x)", eglGetError()); - return CopyResult::UnknownError; - } - - uint32_t width = graphicBuffer->getWidth(); - uint32_t height = graphicBuffer->getHeight(); - CopyResult copyResult = - copyImageInto(sourceImage, texTransform, width, height, srcRect, bitmap); - - // All we're flushing & finishing is the deletion of the texture since - // copyImageInto already did a major flush & finish as an implicit - // part of glReadPixels, so this shouldn't pose any major stalls. - glFinish(); - eglDestroyImageKHR(display, sourceImage); - return copyResult; -} - -CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) { - Rect srcRect; - Matrix4 transform; - transform.loadScale(1, -1, 1); - transform.translate(0, -1); - return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap); -} - -static float sFlipVInit[16] = { - 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, -}; - -static const Matrix4 sFlipV(sFlipVInit); - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState, Texture& sourceTexture, - const Matrix4& texTransform, const Rect& srcRect, - SkBitmap* bitmap) { - int destWidth = bitmap->width(); - int destHeight = bitmap->height(); - if (destWidth > caches.maxTextureSize || destHeight > caches.maxTextureSize) { - ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d", destWidth, - destHeight, caches.maxTextureSize); - return CopyResult::DestinationInvalid; - } - - if (bitmap->colorType() == kRGBA_F16_SkColorType && - !caches.extensions().hasRenderableFloatTextures()) { - ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported"); - return CopyResult::DestinationInvalid; - } - - GLuint fbo = renderState.createFramebuffer(); - if (!fbo) { - ALOGW("Could not obtain an FBO"); - return CopyResult::UnknownError; - } - - GLuint texture; - - GLenum format; - GLenum internalFormat; - GLenum type; - - switch (bitmap->colorType()) { - case kAlpha_8_SkColorType: - format = GL_ALPHA; - internalFormat = GL_ALPHA; - type = GL_UNSIGNED_BYTE; - break; - case kRGB_565_SkColorType: - format = GL_RGB; - internalFormat = GL_RGB; - type = GL_UNSIGNED_SHORT_5_6_5; - break; - case kARGB_4444_SkColorType: - format = GL_RGBA; - internalFormat = GL_RGBA; - type = GL_UNSIGNED_SHORT_4_4_4_4; - break; - case kRGBA_F16_SkColorType: - format = GL_RGBA; - internalFormat = GL_RGBA16F; - type = GL_HALF_FLOAT; - break; - case kN32_SkColorType: - default: - format = GL_RGBA; - internalFormat = GL_RGBA; - type = GL_UNSIGNED_BYTE; - break; - } - - renderState.bindFramebuffer(fbo); - - // TODO: Use layerPool or something to get this maybe? But since we - // need explicit format control we can't currently. - - // Setup the rendertarget - glGenTextures(1, &texture); - caches.textureState().activateTexture(0); - caches.textureState().bindTexture(texture); - glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, destWidth, destHeight, 0, format, type, nullptr); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - - { - bool requiresFilter; - // Draw & readback - renderState.setViewport(destWidth, destHeight); - renderState.scissor().setEnabled(false); - renderState.blend().syncEnabled(); - renderState.stencil().disable(); - - Matrix4 croppedTexTransform(texTransform); - if (!srcRect.isEmpty()) { - // We flipV to convert to 0,0 top-left for the srcRect - // coordinates then flip back to 0,0 bottom-left for - // GLES coordinates. - croppedTexTransform.multiply(sFlipV); - croppedTexTransform.translate(srcRect.left / sourceTexture.width(), - srcRect.top / sourceTexture.height(), 0); - croppedTexTransform.scale(srcRect.getWidth() / sourceTexture.width(), - srcRect.getHeight() / sourceTexture.height(), 1); - croppedTexTransform.multiply(sFlipV); - requiresFilter = srcRect.getWidth() != (float)destWidth || - srcRect.getHeight() != (float)destHeight; - } else { - requiresFilter = sourceTexture.width() != (uint32_t)destWidth || - sourceTexture.height() != (uint32_t)destHeight; - } - Glop glop; - GlopBuilder(renderState, caches, &glop) - .setRoundRectClipState(nullptr) - .setMeshTexturedUnitQuad(nullptr) - .setFillExternalTexture(sourceTexture, croppedTexTransform, requiresFilter) - .setTransform(Matrix4::identity(), TransformFlags::None) - .setModelViewMapUnitToRect(Rect(destWidth, destHeight)) - .build(); - Matrix4 ortho; - ortho.loadOrtho(destWidth, destHeight); - renderState.render(glop, ortho, false); - - // TODO: We should convert to linear space when the target is RGBA16F - glReadPixels(0, 0, bitmap->width(), bitmap->height(), format, type, bitmap->getPixels()); - bitmap->notifyPixelsChanged(); - } - - // Cleanup - caches.textureState().deleteTexture(texture); - renderState.deleteFramebuffer(fbo); - - GL_CHECKPOINT(MODERATE); - - return CopyResult::Success; -} - -CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform, - int imgWidth, int imgHeight, const Rect& srcRect, - SkBitmap* bitmap) { - // If this is a 90 or 270 degree rotation we need to swap width/height - // This is a fuzzy way of checking that. - if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) { - std::swap(imgWidth, imgHeight); - } - - Caches& caches = Caches::getInstance(); - GLuint sourceTexId; - // Create a 2D texture to sample from the EGLImage - glGenTextures(1, &sourceTexId); - caches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage); - - GLenum status = GL_NO_ERROR; - while ((status = glGetError()) != GL_NO_ERROR) { - ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status); - return CopyResult::UnknownError; - } - - Texture sourceTexture(caches); - sourceTexture.wrap(sourceTexId, imgWidth, imgHeight, 0, 0 /* total lie */, - GL_TEXTURE_EXTERNAL_OES); - - CopyResult copyResult = copyTextureInto(caches, mRenderThread.renderState(), sourceTexture, - imgTransform, srcRect, bitmap); - sourceTexture.deleteTexture(); - return copyResult; -} - -bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer, - SkBitmap* bitmap) { - if (!layer.isRenderable()) { - // layer has never been updated by DeferredLayerUpdater, abort copy - return false; - } - - return CopyResult::Success == copyTextureInto(Caches::getInstance(), renderThread.renderState(), - layer.getTexture(), layer.getTexTransform(), - Rect(), bitmap); -} - -} // namespace uirenderer -} // namespace android diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 0d1257fc7b122..064763f65e099 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -215,10 +215,5 @@ void Properties::overrideRenderPipelineType(RenderPipelineType type) { sRenderPipelineType = type; } -bool Properties::isSkiaEnabled() { - auto renderType = getRenderPipelineType(); - return RenderPipelineType::SkiaGL == renderType || RenderPipelineType::SkiaVulkan == renderType; -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 03a3e36c44959..5376bab50b585 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -247,7 +247,6 @@ public: static ProfileType getProfileType(); ANDROID_API static RenderPipelineType getRenderPipelineType(); - static bool isSkiaEnabled(); ANDROID_API static bool enableHighContrastText; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 5ac330bcadb8a..62b80c43ebb7f 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -114,11 +114,7 @@ void RenderNode::prepareTree(TreeInfo& info) { LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing"); MarkAndSweepRemoved observer(&info); - // The OpenGL renderer reserves the stencil buffer for overdraw debugging. Functors - // will need to be drawn in a layer. - bool functorsNeedLayer = Properties::debugOverdraw && !Properties::isSkiaEnabled(); - - prepareTreeImpl(observer, info, functorsNeedLayer); + prepareTreeImpl(observer, info, false); } void RenderNode::addAnimator(const sp& animator) { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 40b811d813fdc..6bd12f4c7ff3a 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -62,13 +62,7 @@ SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) { mCanvasOwned = std::unique_ptr(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy)); if (cs.get() == nullptr || cs->isSRGB()) { - if (!uirenderer::Properties::isSkiaEnabled()) { - mCanvasWrapper = - SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), SkColorSpace::MakeSRGB()); - mCanvas = mCanvasWrapper.get(); - } else { - mCanvas = mCanvasOwned.get(); - } + mCanvas = mCanvasOwned.get(); } else { /** The wrapper is needed if we are drawing into a non-sRGB destination, since * we need to transform all colors (not just bitmaps via filters) into the @@ -101,8 +95,6 @@ void SkiaCanvas::setBitmap(const SkBitmap& bitmap) { std::unique_ptr newCanvasWrapper; if (cs.get() != nullptr && !cs->isSRGB()) { newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs)); - } else if (!uirenderer::Properties::isSkiaEnabled()) { - newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), SkColorSpace::MakeSRGB()); } // deletes the previously owned canvas (if any) diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index 795ec5bd4f768..beb4a9e185a37 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -205,10 +205,8 @@ Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info) mPixelStorage.hardware.buffer = buffer; buffer->incStrong(buffer); setImmutable(); // HW bitmaps are always immutable - if (uirenderer::Properties::isSkiaEnabled()) { - mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast(buffer), - mInfo.alphaType(), mInfo.refColorSpace()); - } + mImage = SkImage::MakeFromAHardwareBuffer(reinterpret_cast(buffer), + mInfo.alphaType(), mInfo.refColorSpace()); } Bitmap::~Bitmap() { @@ -288,13 +286,9 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) { void Bitmap::getSkBitmap(SkBitmap* outBitmap) { outBitmap->setHasHardwareMipMap(mHasHardwareMipMap); if (isHardware()) { - if (uirenderer::Properties::isSkiaEnabled()) { outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(), info().colorType(), info().alphaType(), nullptr)); - } else { - outBitmap->allocPixels(info()); - } uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap); return; } @@ -317,7 +311,7 @@ GraphicBuffer* Bitmap::graphicBuffer() { sk_sp Bitmap::makeImage(sk_sp* outputColorFilter) { sk_sp image = mImage; if (!image) { - SkASSERT(!(isHardware() && uirenderer::Properties::isSkiaEnabled())); + SkASSERT(!isHardware()); SkBitmap skiaBitmap; skiaBitmap.setInfo(info(), rowBytes()); skiaBitmap.setPixelRef(sk_ref_sp(this), 0, 0); @@ -327,8 +321,7 @@ sk_sp Bitmap::makeImage(sk_sp* outputColorFilter) { // TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here. image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode); } - if (uirenderer::Properties::isSkiaEnabled() && image->colorSpace() != nullptr && - !image->colorSpace()->isSRGB()) { + if (image->colorSpace() != nullptr && !image->colorSpace()->isSRGB()) { *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace()); } return image; diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp index 20543df850683..b453227ba770e 100644 --- a/libs/hwui/hwui/Canvas.cpp +++ b/libs/hwui/hwui/Canvas.cpp @@ -29,10 +29,7 @@ namespace android { Canvas* Canvas::create_recording_canvas(int width, int height, uirenderer::RenderNode* renderNode) { - if (uirenderer::Properties::isSkiaEnabled()) { - return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height); - } - return new uirenderer::RecordingCanvas(width, height); + return new uirenderer::skiapipeline::SkiaRecordingCanvas(renderNode, width, height); } static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkScalar thickness, diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp index 4393f459315cb..208910a06eaaa 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp @@ -136,6 +136,8 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4 // make sure that we have deleted the texture (in the SkImage) before we // destroy the EGLImage that it was created from image.reset(); + glFinish(); + return copyResult; } diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h index cc9fb3b0a5e07..1ce4773e7d674 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h @@ -16,15 +16,15 @@ #pragma once -#include "OpenGLReadback.h" +#include "EglReadback.h" namespace android { namespace uirenderer { namespace skiapipeline { -class SkiaOpenGLReadback : public OpenGLReadback { +class SkiaOpenGLReadback : public EglReadback { public: - SkiaOpenGLReadback(renderthread::RenderThread& thread) : OpenGLReadback(thread) {} + SkiaOpenGLReadback(renderthread::RenderThread& thread) : EglReadback(thread) {} protected: virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform, diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index f510a20553095..b07fb2d7ae0f7 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -50,9 +50,7 @@ CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas( mMaxSurfaceArea / 2, skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface); - if (Properties::isSkiaEnabled()) { - skiapipeline::ShaderCache::get().initShaderDiskCache(); - } + skiapipeline::ShaderCache::get().initShaderDiskCache(); } void CacheManager::reset(sk_sp context) { diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index a0fc83e94f6a9..3deed6e0ba774 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -23,7 +23,6 @@ #include "EglManager.h" #include "Frame.h" #include "LayerUpdateQueue.h" -#include "OpenGLPipeline.h" #include "Properties.h" #include "RenderThread.h" #include "hwui/Canvas.h" diff --git a/libs/hwui/renderthread/OpenGLPipeline.cpp b/libs/hwui/renderthread/OpenGLPipeline.cpp deleted file mode 100644 index 19258084eb42f..0000000000000 --- a/libs/hwui/renderthread/OpenGLPipeline.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#include "OpenGLPipeline.h" - -#include "DeferredLayerUpdater.h" -#include "EglManager.h" -#include "Frame.h" -#include "GlLayer.h" -#include "OpenGLReadback.h" -#include "ProfileRenderer.h" -#include "TreeInfo.h" -#include "renderstate/RenderState.h" - -#include -#include - -namespace android { -namespace uirenderer { -namespace renderthread { - -OpenGLPipeline::OpenGLPipeline(RenderThread& thread) - : mEglManager(thread.eglManager()), mRenderThread(thread) {} - -MakeCurrentResult OpenGLPipeline::makeCurrent() { - // TODO: Figure out why this workaround is needed, see b/13913604 - // In the meantime this matches the behavior of GLRenderer, so it is not a regression - EGLint error = 0; - bool haveNewSurface = mEglManager.makeCurrent(mEglSurface, &error); - - Caches::getInstance().textureCache.resetMarkInUse(this); - if (!haveNewSurface) { - return MakeCurrentResult::AlreadyCurrent; - } - return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded; -} - -Frame OpenGLPipeline::getFrame() { - LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, - "drawRenderNode called on a context with no surface!"); - return mEglManager.beginFrame(mEglSurface); -} - -bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty, - const FrameBuilder::LightGeometry& lightGeometry, - LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds, - bool opaque, bool wideColorGamut, - const BakedOpRenderer::LightInfo& lightInfo, - const std::vector>& renderNodes, - FrameInfoVisualizer* profiler) { - mEglManager.damageFrame(frame, dirty); - - bool drew = false; - - auto& caches = Caches::getInstance(); - FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), lightGeometry, caches); - - frameBuilder.deferLayers(*layerUpdateQueue); - layerUpdateQueue->clear(); - - frameBuilder.deferRenderNodeScene(renderNodes, contentDrawBounds); - - BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut, - lightInfo); - frameBuilder.replayBakedOps(renderer); - ProfileRenderer profileRenderer(renderer); - profiler->draw(profileRenderer); - drew = renderer.didDraw(); - - // post frame cleanup - caches.clearGarbage(); - caches.pathCache.trim(); - caches.tessellationCache.trim(); - -#if DEBUG_MEMORY_USAGE - caches.dumpMemoryUsage(); -#else - if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) { - caches.dumpMemoryUsage(); - } -#endif - - return drew; -} - -bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty, - FrameInfo* currentFrameInfo, bool* requireSwap) { - GL_CHECKPOINT(LOW); - - // Even if we decided to cancel the frame, from the perspective of jank - // metrics the frame was swapped at this point - currentFrameInfo->markSwapBuffers(); - - *requireSwap = drew || mEglManager.damageRequiresSwap(); - - if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) { - return false; - } - - return *requireSwap; -} - -bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { - ATRACE_CALL(); - // acquire most recent buffer for drawing - layer->updateTexImage(); - layer->apply(); - return OpenGLReadbackImpl::copyLayerInto(mRenderThread, - static_cast(*layer->backingLayer()), bitmap); -} - -static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight, - SkColorFilter* colorFilter, int alpha, SkBlendMode mode, bool blend) { - GlLayer* layer = - new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend); - Caches::getInstance().textureState().activateTexture(0); - layer->generateTexture(); - return layer; -} - -DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() { - mEglManager.initialize(); - return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL); -} - -void OpenGLPipeline::onStop() { - if (mEglManager.isCurrent(mEglSurface)) { - mEglManager.makeCurrent(EGL_NO_SURFACE); - } -} - -bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior, ColorMode colorMode) { - if (mEglSurface != EGL_NO_SURFACE) { - mEglManager.destroySurface(mEglSurface); - mEglSurface = EGL_NO_SURFACE; - } - - if (surface) { - const bool wideColorGamut = colorMode == ColorMode::WideColorGamut; - mEglSurface = mEglManager.createSurface(surface, wideColorGamut); - } - - if (mEglSurface != EGL_NO_SURFACE) { - const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer); - mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer); - return true; - } - - return false; -} - -bool OpenGLPipeline::isSurfaceReady() { - return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE); -} - -bool OpenGLPipeline::isContextReady() { - return CC_LIKELY(mEglManager.hasEglContext()); -} - -void OpenGLPipeline::onDestroyHardwareResources() { - Caches& caches = Caches::getInstance(); - // Make sure to release all the textures we were owning as there won't - // be another draw - caches.textureCache.resetMarkInUse(this); - mRenderThread.renderState().flush(Caches::FlushMode::Layers); -} - -void OpenGLPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry, - LayerUpdateQueue* layerUpdateQueue, bool opaque, - bool wideColorGamut, - const BakedOpRenderer::LightInfo& lightInfo) { - static const std::vector> emptyNodeList; - auto& caches = Caches::getInstance(); - FrameBuilder frameBuilder(*layerUpdateQueue, lightGeometry, caches); - layerUpdateQueue->clear(); - // TODO: Handle wide color gamut contexts - BakedOpRenderer renderer(caches, mRenderThread.renderState(), opaque, wideColorGamut, - lightInfo); - LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case"); - frameBuilder.replayBakedOps(renderer); -} - -TaskManager* OpenGLPipeline::getTaskManager() { - return &Caches::getInstance().tasks; -} - -static bool layerMatchesWH(OffscreenBuffer* layer, int width, int height) { - return layer->viewportWidth == (uint32_t)width && layer->viewportHeight == (uint32_t)height; -} - -bool OpenGLPipeline::createOrUpdateLayer(RenderNode* node, - const DamageAccumulator& damageAccumulator, - bool wideColorGamut, ErrorHandler* errorHandler) { - RenderState& renderState = mRenderThread.renderState(); - OffscreenBufferPool& layerPool = renderState.layerPool(); - bool transformUpdateNeeded = false; - if (node->getLayer() == nullptr) { - node->setLayer( - layerPool.get(renderState, node->getWidth(), node->getHeight(), wideColorGamut)); - transformUpdateNeeded = true; - } else if (!layerMatchesWH(node->getLayer(), node->getWidth(), node->getHeight())) { - // TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering) - // Or, ideally, maintain damage between frames on node/layer so ordering is always correct - if (node->properties().fitsOnLayer()) { - node->setLayer(layerPool.resize(node->getLayer(), node->getWidth(), node->getHeight())); - } else { - destroyLayer(node); - } - transformUpdateNeeded = true; - } - - if (transformUpdateNeeded && node->getLayer()) { - // update the transform in window of the layer to reset its origin wrt light source position - Matrix4 windowTransform; - damageAccumulator.computeCurrentTransform(&windowTransform); - node->getLayer()->setWindowTransform(windowTransform); - } - - if (!node->hasLayer()) { - Caches::getInstance().dumpMemoryUsage(); - if (errorHandler) { - std::ostringstream err; - err << "Unable to create layer for " << node->getName(); - const int maxTextureSize = Caches::getInstance().maxTextureSize; - if (node->getWidth() > maxTextureSize || node->getHeight() > maxTextureSize) { - err << ", size " << node->getWidth() << "x" << node->getHeight() - << " exceeds max size " << maxTextureSize; - } else { - err << ", see logcat for more info"; - } - errorHandler->onError(err.str()); - } - } - - return transformUpdateNeeded; -} - -bool OpenGLPipeline::pinImages(LsaVector>& images) { - TextureCache& cache = Caches::getInstance().textureCache; - bool prefetchSucceeded = true; - for (auto& bitmapResource : images) { - prefetchSucceeded &= cache.prefetchAndMarkInUse(this, bitmapResource.get()); - } - return prefetchSucceeded; -} - -void OpenGLPipeline::unpinImages() { - Caches::getInstance().textureCache.resetMarkInUse(this); -} - -void OpenGLPipeline::destroyLayer(RenderNode* node) { - if (OffscreenBuffer* layer = node->getLayer()) { - layer->renderState.layerPool().putOrDelete(layer); - node->setLayer(nullptr); - } -} - -void OpenGLPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) { - if (Caches::hasInstance() && thread.eglManager().hasEglContext()) { - ATRACE_NAME("Bitmap#prepareToDraw task"); - Caches::getInstance().textureCache.prefetch(bitmap); - } -} - -void OpenGLPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) { - DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; - if (thread.eglManager().hasEglContext()) { - mode = DrawGlInfo::kModeProcess; - } - thread.renderState().invokeFunctor(functor, mode, nullptr); -} - -#define FENCE_TIMEOUT 2000000000 - -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; -}; - -class AutoGlTexture { -public: - AutoGlTexture(uirenderer::Caches& caches) : mCaches(caches) { - glGenTextures(1, &mTexture); - caches.textureState().bindTexture(mTexture); - } - - ~AutoGlTexture() { mCaches.textureState().deleteTexture(mTexture); } - -private: - uirenderer::Caches& mCaches; - GLuint mTexture = 0; -}; - -static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap, - GraphicBuffer& buffer, GLint format, GLint type) { - EGLDisplay display = eglGetCurrentDisplay(); - LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s", - uirenderer::renderthread::EglManager::eglErrorString()); - // 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; - } - AutoGlTexture glTexture(caches); - 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; -} - -// TODO: handle SRGB sanely -static PixelFormat internalFormatToPixelFormat(GLint internalFormat) { - switch (internalFormat) { - 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; - case GL_RGB: - return PIXEL_FORMAT_RGB_565; - case GL_RGBA16F: - return PIXEL_FORMAT_RGBA_FP16; - default: - LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat); - return PIXEL_FORMAT_UNKNOWN; - } -} - -sk_sp OpenGLPipeline::allocateHardwareBitmap(RenderThread& renderThread, - SkBitmap& skBitmap) { - renderThread.eglManager().initialize(); - uirenderer::Caches& caches = uirenderer::Caches::getInstance(); - - const SkImageInfo& info = skBitmap.info(); - if (info.colorType() == kUnknown_SkColorType || info.colorType() == kAlpha_8_SkColorType) { - ALOGW("unable to create hardware bitmap of colortype: %d", info.colorType()); - return nullptr; - } - - bool needSRGB = uirenderer::transferFunctionCloseToSRGB(skBitmap.info().colorSpace()); - bool hasLinearBlending = caches.extensions().hasLinearBlending(); - GLint format, type, internalFormat; - uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(), - needSRGB && hasLinearBlending, &internalFormat, - &format, &type); - - PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat); - sp buffer = new GraphicBuffer( - info.width(), info.height(), pixelFormat, - GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER | - GraphicBuffer::USAGE_SW_READ_NEVER, - std::string("Bitmap::allocateHardwareBitmap pid [") + std::to_string(getpid()) + "]"); - - status_t error = buffer->initCheck(); - if (error < 0) { - ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()"); - return nullptr; - } - - SkBitmap bitmap; - if (CC_UNLIKELY( - uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(), hasLinearBlending))) { - sk_sp sRGB = SkColorSpace::MakeSRGB(); - bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB)); - } else { - bitmap = skBitmap; - } - - if (!uploadBitmapToGraphicBuffer(caches, bitmap, *buffer, format, type)) { - return nullptr; - } - return sk_sp(new Bitmap(buffer.get(), bitmap.info())); -} - -} /* namespace renderthread */ -} /* namespace uirenderer */ -} /* namespace android */ diff --git a/libs/hwui/renderthread/OpenGLPipeline.h b/libs/hwui/renderthread/OpenGLPipeline.h deleted file mode 100644 index 9859e931fd85d..0000000000000 --- a/libs/hwui/renderthread/OpenGLPipeline.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#pragma once - -#include "BakedOpDispatcher.h" -#include "BakedOpRenderer.h" -#include "CanvasContext.h" -#include "FrameBuilder.h" -#include "IRenderPipeline.h" - -namespace android { -namespace uirenderer { -namespace renderthread { - -class OpenGLPipeline : public IRenderPipeline { -public: - OpenGLPipeline(RenderThread& thread); - virtual ~OpenGLPipeline() {} - - MakeCurrentResult makeCurrent() override; - Frame getFrame() override; - bool draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty, - const FrameBuilder::LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue, - const Rect& contentDrawBounds, bool opaque, bool wideColorGamut, - const BakedOpRenderer::LightInfo& lightInfo, - const std::vector>& renderNodes, - FrameInfoVisualizer* profiler) override; - bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty, - FrameInfo* currentFrameInfo, bool* requireSwap) override; - bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override; - DeferredLayerUpdater* createTextureLayer() override; - bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) override; - void onStop() override; - bool isSurfaceReady() override; - bool isContextReady() override; - void onDestroyHardwareResources() override; - void renderLayers(const FrameBuilder::LightGeometry& lightGeometry, - LayerUpdateQueue* layerUpdateQueue, bool opaque, bool wideColorGamut, - const BakedOpRenderer::LightInfo& lightInfo) override; - TaskManager* getTaskManager() override; - bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator, - bool wideColorGamut, ErrorHandler* errorHandler) override; - bool pinImages(std::vector& mutableImages) override { return false; } - bool pinImages(LsaVector>& images) override; - void unpinImages() override; - void onPrepareTree() override {} - static void destroyLayer(RenderNode* node); - static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap); - static void invokeFunctor(const RenderThread& thread, Functor* functor); - static sk_sp allocateHardwareBitmap(RenderThread& thread, SkBitmap& skBitmap); - -private: - EglManager& mEglManager; - EGLSurface mEglSurface = EGL_NO_SURFACE; - bool mBufferPreserved = false; - RenderThread& mRenderThread; -}; - -} /* namespace renderthread */ -} /* namespace uirenderer */ -} /* namespace android */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index a1a2bad41bf7b..653ea2808ae7a 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -334,7 +334,7 @@ sk_sp RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) { int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) { RenderThread& thread = RenderThread::getInstance(); - if (Properties::isSkiaEnabled() && gettid() == thread.getTid()) { + if (gettid() == thread.getTid()) { // TODO: fix everything that hits this. We should never be triggering a readback ourselves. return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap); } else { diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index f4d230e7c76cd..84f43ec1a206d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -19,7 +19,6 @@ #include "CanvasContext.h" #include "DeviceInfo.h" #include "EglManager.h" -#include "OpenGLReadback.h" #include "RenderProxy.h" #include "VulkanManager.h" #include "hwui/Bitmap.h" @@ -28,7 +27,6 @@ #include "pipeline/skia/SkiaVulkanPipeline.h" #include "pipeline/skia/SkiaVulkanReadback.h" #include "renderstate/RenderState.h" -#include "renderthread/OpenGLPipeline.h" #include "utils/FatVector.h" #include "utils/TimeUtils.h" diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp index f51e7cc04d8d9..16c5afdc3dcf1 100644 --- a/libs/hwui/tests/common/TestUtils.cpp +++ b/libs/hwui/tests/common/TestUtils.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include