aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Stan Iliev <stani@google.com>2017-06-28 13:24:41 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-28 17:56:46 +0000
commitdbba55de7026c0ffbf1eff057d7bf87c19ec80d1 (patch)
tree0ef2df8e5568aa1dd558cd63836b049ff40d9cae /src
parentc2d207603edbbd3809d5144fe4a048a2ad774910 (diff)
Cache GrTexture in GrAHardwareBufferImageGenerator
Cache last GrTexture needed by onGenerateTexture. Make sure GrTexture is destroyed by the thread that owns its GrContext. This CL avoids frequent eglDestroyImageKHR calls, which can take more than 7ms. Bug: skia: Change-Id: Ic8472e7e4c55c0f559d96e16845054dc54ec8efa Reviewed-on: https://skia-review.googlesource.com/20989 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Stan Iliev <stani@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrAHardwareBufferImageGenerator.cpp86
-rw-r--r--src/gpu/GrAHardwareBufferImageGenerator.h4
2 files changed, 58 insertions, 32 deletions
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index 8f6cb886e9..b05605c4a0 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -17,9 +17,11 @@
#include "GrBackendSurface.h"
#include "GrContext.h"
#include "GrContextPriv.h"
+#include "GrResourceCache.h"
#include "GrResourceProvider.h"
#include "GrTexture.h"
#include "GrTextureProxy.h"
+#include "SkMessageBus.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -72,11 +74,22 @@ GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageIn
GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
AHardwareBuffer_release(fGraphicBuffer);
+ this->clear();
+}
+
+void GrAHardwareBufferImageGenerator::clear() {
+ if (fOriginalTexture) {
+ // Notify the original cache that it can free the last ref, so it happens on the correct
+ // thread.
+ GrGpuResourceFreedMessage msg { fOriginalTexture, fOwningContextID };
+ SkMessageBus<GrGpuResourceFreedMessage>::Post(msg);
+ fOriginalTexture = nullptr;
+ }
}
void GrAHardwareBufferImageGenerator::deleteImageTexture(void* context) {
- BufferCleanupHelper* cleanupHelper = static_cast<BufferCleanupHelper*>(context);
- delete cleanupHelper;
+ BufferCleanupHelper* cleanupHelper = static_cast<BufferCleanupHelper*>(context);
+ delete cleanupHelper;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -86,14 +99,36 @@ void GrAHardwareBufferImageGenerator::deleteImageTexture(void* context) {
sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
GrContext* context, const SkImageInfo& info, const SkIPoint& origin) {
- // TODO: return a cached GrTextureProxy if invoked with the same context
- // TODO: if we cache GrTextureProxy, then deleteImageTexture may be invoked on the wrong thread
+ auto proxy = this->makeProxy(context);
+ if (!proxy) {
+ return nullptr;
+ }
+ if (0 == origin.fX && 0 == origin.fY &&
+ info.width() == getInfo().width() && info.height() == getInfo().height()) {
+ // If the caller wants the entire texture, we're done
+ return proxy;
+ } else {
+ // Otherwise, make a copy of the requested subset.
+ return GrSurfaceProxy::Copy(context, proxy.get(),
+ SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(),
+ info.height()),
+ SkBudgeted::kYes);
+ }
+}
+#endif
+
+sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
if (!context->getGpu() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
// Check if GrContext is not abandoned and the backend is GL.
return nullptr;
}
+ // return a cached GrTexture if invoked with the same context
+ if (fOriginalTexture && fOwningContextID == context->uniqueID()) {
+ return GrSurfaceProxy::MakeWrapped(sk_ref_sp(fOriginalTexture));
+ }
+
while (GL_NO_ERROR != glGetError()) {} //clear GL errors
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(fGraphicBuffer);
@@ -168,36 +203,23 @@ sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
return nullptr;
}
tex->setRelease(deleteImageTexture, new BufferCleanupHelper(image, display));
- sk_sp<GrTextureProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(tex)));
- if (0 == origin.fX && 0 == origin.fY &&
- info.width() == backendTex.width() && info.height() == backendTex.height()) {
- // If the caller wants the entire texture, we're done
- return proxy;
- } else {
- // Otherwise, make a copy of the requested subset.
- GrSurfaceDesc desc;
- desc.fConfig = proxy->config();
- desc.fWidth = info.width();
- desc.fHeight = info.height();
- desc.fOrigin = proxy->origin();
- desc.fIsMipMapped = proxy->isMipMapped();
-
- sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeDeferredSurfaceContext(
- desc, SkBackingFit::kExact, SkBudgeted::kYes));
- if (!sContext) {
- return nullptr;
- }
-
- SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
- if (!sContext->copy(proxy.get(), subset, SkIPoint::Make(0, 0))) {
- return nullptr;
- }
-
- return sContext->asTextureProxyRef();
- }
+ // We fail this assert, if the context has changed. This will be fully handled after
+ // skbug.com/6812 is ready.
+ SkASSERT(!fOriginalTexture);
+
+ this->clear();
+ fOriginalTexture = tex.get();
+ fOwningContextID = context->uniqueID();
+ // Attach our texture to this context's resource cache. This ensures that deletion will happen
+ // in the correct thread/context. This adds the only ref to the texture that will persist from
+ // this point. To trigger GrTexture deletion a message is sent by generator dtor or by
+ // makeProxy when it is invoked with a different context.
+ //TODO: GrResourceCache should delete GrTexture, when GrContext is deleted. Currently
+ //TODO: SkMessageBus ignores messages for deleted contexts and GrTexture will leak.
+ context->getResourceCache()->insertCrossContextGpuResource(fOriginalTexture);
+ return GrSurfaceProxy::MakeWrapped(std::move(tex));
}
-#endif
bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
if (nullptr == context) {
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.h b/src/gpu/GrAHardwareBufferImageGenerator.h
index e758138507..f23738b9c5 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.h
+++ b/src/gpu/GrAHardwareBufferImageGenerator.h
@@ -41,10 +41,14 @@ protected:
private:
GrAHardwareBufferImageGenerator(const SkImageInfo&, AHardwareBuffer*, SkAlphaType);
+ sk_sp<GrTextureProxy> makeProxy(GrContext* context);
+ void clear();
static void deleteImageTexture(void* ctx);
AHardwareBuffer* fGraphicBuffer;
+ GrTexture* fOriginalTexture = nullptr;
+ uint32_t fOwningContextID;
typedef SkImageGenerator INHERITED;
};