aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrAHardwareBufferImageGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrAHardwareBufferImageGenerator.cpp')
-rw-r--r--src/gpu/GrAHardwareBufferImageGenerator.cpp86
1 files changed, 54 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) {