Revert "Add GrExternalTextureData and SkCrossContextImageData"

This reverts commit 9ad1f92e2f.

Reason for revert: Breaking lots of bots

Original change's description:
> Add GrExternalTextureData and SkCrossContextImageData
> 
> GrExternalTextureData is an API for exporting the backend-specific
> information about a texture in a type-safe way, and without pointing
> into the GrTexture. The new detachBackendTexture API lets us release
> ownership of a texture to the client.
> 
> SkCrossContextImageData is the public API that lets clients upload
> textures on one thread/GrContext, then safely transfer ownership to
> another thread and GrContext for rendering.
> 
> Only GL is implemented/supported right now. Vulkan support requires
> that we add thread-safe memory pools, or otherwise transfer the
> actual memory block containing the texture to the new context.
> 
> BUG=skia:
> 
> Change-Id: I784a3a74be69807df038c7d192eaed002c7e45ca
> Reviewed-on: https://skia-review.googlesource.com/8529
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> 

TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com,brianosman@google.com,reviews@skia.org,chinmaygarde@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:

Change-Id: If27d1f4c3a169efb6533170f67a172664c0fe8ce
Reviewed-on: https://skia-review.googlesource.com/8955
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2017-02-24 17:27:52 +00:00 committed by Skia Commit-Bot
parent 11d2df0bdd
commit aa1ab8905e
30 changed files with 2 additions and 553 deletions

View File

@ -390,7 +390,6 @@ skia_core_sources = [
"$_include/core/SkColor.h", "$_include/core/SkColor.h",
"$_include/core/SkColorFilter.h", "$_include/core/SkColorFilter.h",
"$_include/core/SkColorPriv.h", "$_include/core/SkColorPriv.h",
"$_include/core/SkCrossContextImageData.h",
"$_include/core/SkData.h", "$_include/core/SkData.h",
"$_include/core/SkDeque.h", "$_include/core/SkDeque.h",
"$_include/core/SkDrawable.h", "$_include/core/SkDrawable.h",

View File

@ -18,7 +18,6 @@ skia_gpu_sources = [
"$_include/gpu/GrContextOptions.h", "$_include/gpu/GrContextOptions.h",
"$_include/gpu/GrContext.h", "$_include/gpu/GrContext.h",
"$_include/gpu/GrCoordTransform.h", "$_include/gpu/GrCoordTransform.h",
"$_include/gpu/GrExternalTextureData.h",
"$_include/gpu/GrFragmentProcessor.h", "$_include/gpu/GrFragmentProcessor.h",
"$_include/gpu/GrGpuResource.h", "$_include/gpu/GrGpuResource.h",
"$_include/gpu/GrPaint.h", "$_include/gpu/GrPaint.h",

View File

@ -44,7 +44,6 @@ tests_sources = [
"$_tests/ColorTest.cpp", "$_tests/ColorTest.cpp",
"$_tests/CopySurfaceTest.cpp", "$_tests/CopySurfaceTest.cpp",
"$_tests/CPlusPlusEleven.cpp", "$_tests/CPlusPlusEleven.cpp",
"$_tests/CrossContextImageTest.cpp",
"$_tests/CTest.cpp", "$_tests/CTest.cpp",
"$_tests/DashPathEffectTest.cpp", "$_tests/DashPathEffectTest.cpp",
"$_tests/DataRefTest.cpp", "$_tests/DataRefTest.cpp",

View File

@ -1,68 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkCrossContextImageData_DEFINED
#define SkCrossContextImageData_DEFINED
#include "SkImage.h"
#if SK_SUPPORT_GPU
#include "GrExternalTextureData.h"
#endif
class SK_API SkCrossContextImageData : SkNoncopyable {
public:
/**
* Decodes and uploads the encoded data to a texture using the supplied GrContext, then
* returns an instance of SkCrossContextImageData that can be used to transport that texture
* to a different GrContext, across thread boundaries. The GrContext used here, and the one
* used to reconstruct the texture-backed image later must be in the same GL share group,
* or otherwise be able to share resources. After calling this, you *must* construct exactly
* one SkImage from the returned value, using SkImage::MakeFromCrossContextImageData.
*
* The texture will be decoded and uploaded to be suitable for use with surfaces that have the
* supplied destination color space. The color space of the texture itself will be determined
* from the encoded data.
*/
static std::unique_ptr<SkCrossContextImageData> MakeFromEncoded(
GrContext*, sk_sp<SkData>, SkColorSpace* dstColorSpace);
private:
SkCrossContextImageData(sk_sp<SkImage> image) : fImage(std::move(image)) {
SkASSERT(!fImage->isTextureBacked());
}
#if SK_SUPPORT_GPU
SkCrossContextImageData(const GrBackendTextureDesc& desc,
std::unique_ptr<GrExternalTextureData> textureData,
SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace)
: fAlphaType(alphaType)
, fColorSpace(std::move(colorSpace))
, fDesc(desc)
, fTextureData(std::move(textureData)) {
// Point our texture desc at our copy of the backend information
fDesc.fTextureHandle = fTextureData->getBackendObject();
}
#endif
// For non-GPU backed images
sk_sp<SkImage> fImage;
#if SK_SUPPORT_GPU
// GPU-backed images store some generic information (needed to reconstruct the SkImage),
// and some backend-specific info (to reconstruct the texture).
SkAlphaType fAlphaType;
sk_sp<SkColorSpace> fColorSpace;
GrBackendTextureDesc fDesc;
std::unique_ptr<GrExternalTextureData> fTextureData;
#endif
friend class SkImage;
};
#endif

View File

@ -18,7 +18,6 @@
class SkData; class SkData;
class SkCanvas; class SkCanvas;
class SkColorTable; class SkColorTable;
class SkCrossContextImageData;
class SkImageGenerator; class SkImageGenerator;
class SkPaint; class SkPaint;
class SkPicture; class SkPicture;
@ -324,14 +323,6 @@ public:
*/ */
sk_sp<SkImage> makeTextureImage(GrContext*, SkColorSpace* dstColorSpace) const; sk_sp<SkImage> makeTextureImage(GrContext*, SkColorSpace* dstColorSpace) const;
/**
* Constructs a texture backed image from data that was previously uploaded on another thread
* and GrContext. The GrContext used to upload the data must be in the same GL share group as
* the one passed in here, or otherwise be able to share resources with the passed in context.
*/
static sk_sp<SkImage> MakeFromCrossContextImageData(GrContext*,
std::unique_ptr<SkCrossContextImageData>);
/** /**
* If the image is texture-backed this will make a raster copy of it (or nullptr if reading back * If the image is texture-backed this will make a raster copy of it (or nullptr if reading back
* the pixels fails). Otherwise, it returns the original image. * the pixels fails). Otherwise, it returns the original image.

View File

@ -324,12 +324,6 @@ public:
*/ */
void prepareSurfaceForExternalIO(GrSurface*); void prepareSurfaceForExternalIO(GrSurface*);
/**
* As above, but additionally flushes the backend API (eg calls glFlush), and returns a fence
* that can be used to determine if the surface is safe to use on another context or thread.
*/
GrFence SK_WARN_UNUSED_RESULT prepareSurfaceForExternalIOAndFlush(GrSurface*);
/** /**
* An ID associated with this context, guaranteed to be unique. * An ID associated with this context, guaranteed to be unique.
*/ */

View File

@ -1,30 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrExternalTextureData_DEFINED
#define GrExternalTextureData_DEFINED
#include "GrTypes.h"
#include "GrTypesPriv.h"
class SK_API GrExternalTextureData : SkNoncopyable {
public:
GrExternalTextureData(GrFence fence) : fFence(fence) {}
virtual ~GrExternalTextureData() {}
virtual GrBackend getBackend() const = 0;
GrFence getFence() const { return fFence; }
protected:
virtual GrBackendObject getBackendObject() const = 0;
GrFence fFence;
friend class SkCrossContextImageData;
};
#endif

View File

@ -260,11 +260,6 @@ protected:
// final class). // final class).
void registerWithCacheWrapped(); void registerWithCacheWrapped();
// This is only called by resources that are being exported from Ganesh to client code. It
// ensures that the cache can no longer reach this resource, and that it no longer counts
// against the budget.
void detachFromCache();
GrGpuResource(GrGpu*); GrGpuResource(GrGpu*);
virtual ~GrGpuResource(); virtual ~GrGpuResource();

View File

@ -14,7 +14,6 @@
#include "SkPoint.h" #include "SkPoint.h"
#include "SkRefCnt.h" #include "SkRefCnt.h"
class GrExternalTextureData;
class GrTexturePriv; class GrTexturePriv;
class GrTexture : virtual public GrSurface { class GrTexture : virtual public GrSurface {
@ -50,7 +49,6 @@ protected:
GrSamplerParams::FilterMode highestFilterMode, bool wasMipMapDataProvided); GrSamplerParams::FilterMode highestFilterMode, bool wasMipMapDataProvided);
void validateDesc() const; void validateDesc() const;
virtual std::unique_ptr<GrExternalTextureData> detachBackendTexture() = 0;
private: private:
void computeScratchKey(GrScratchKey*) const override; void computeScratchKey(GrScratchKey*) const override;

View File

@ -9,7 +9,6 @@
#ifndef GrGLTypes_DEFINED #ifndef GrGLTypes_DEFINED
#define GrGLTypes_DEFINED #define GrGLTypes_DEFINED
#include "GrExternalTextureData.h"
#include "GrGLConfig.h" #include "GrGLConfig.h"
/** /**
@ -113,23 +112,6 @@ struct GrGLTextureInfo {
GrGLuint fID; GrGLuint fID;
}; };
class GrGLExternalTextureData : public GrExternalTextureData {
public:
GrGLExternalTextureData(const GrGLTextureInfo& info, GrFence fence)
: INHERITED(fence)
, fInfo(info) {}
GrBackend getBackend() const override { return kOpenGL_GrBackend; }
protected:
GrBackendObject getBackendObject() const override {
return reinterpret_cast<GrBackendObject>(&fInfo);
}
GrGLTextureInfo fInfo;
typedef GrExternalTextureData INHERITED;
};
GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrGLTextureInfo*)); GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrGLTextureInfo*));
#endif #endif

View File

@ -9,7 +9,6 @@
#ifndef GrVkTypes_DEFINED #ifndef GrVkTypes_DEFINED
#define GrVkTypes_DEFINED #define GrVkTypes_DEFINED
#include "GrExternalTextureData.h"
#include "GrTypes.h" #include "GrTypes.h"
#include "vk/GrVkDefines.h" #include "vk/GrVkDefines.h"
@ -60,23 +59,6 @@ struct GrVkImageInfo {
void updateImageLayout(VkImageLayout layout) { fImageLayout = layout; } void updateImageLayout(VkImageLayout layout) { fImageLayout = layout; }
}; };
class GrVkExternalTextureData : public GrExternalTextureData {
public:
GrVkExternalTextureData(const GrVkImageInfo& info, GrFence fence)
: INHERITED(fence)
, fInfo(info) {}
GrBackend getBackend() const override { return kVulkan_GrBackend; }
protected:
GrBackendObject getBackendObject() const override {
return reinterpret_cast<GrBackendObject>(&fInfo);
}
GrVkImageInfo fInfo;
typedef GrExternalTextureData INHERITED;
};
GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrVkImageInfo*)); GR_STATIC_ASSERT(sizeof(GrBackendObject) >= sizeof(const GrVkImageInfo*));
#endif #endif

View File

@ -545,13 +545,6 @@ void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
fDrawingManager->prepareSurfaceForExternalIO(surface); fDrawingManager->prepareSurfaceForExternalIO(surface);
} }
GrFence GrContext::prepareSurfaceForExternalIOAndFlush(GrSurface* surface) {
this->prepareSurfaceForExternalIO(surface);
GrFence fence = fGpu->insertFence();
fGpu->flush();
return fence;
}
void GrContext::flushSurfaceWrites(GrSurface* surface) { void GrContext::flushSurfaceWrites(GrSurface* surface) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED RETURN_IF_ABANDONED

View File

@ -382,10 +382,6 @@ public:
virtual bool waitFence(GrFence, uint64_t timeout = 1000) const = 0; virtual bool waitFence(GrFence, uint64_t timeout = 1000) const = 0;
virtual void deleteFence(GrFence) const = 0; virtual void deleteFence(GrFence) const = 0;
// Ensures that all queued up driver-level commands have been sent to the GPU. For example, on
// OpenGL, this calls glFlush.
virtual void flush() = 0;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Debugging and Stats // Debugging and Stats

View File

@ -43,17 +43,6 @@ void GrGpuResource::registerWithCacheWrapped() {
get_resource_cache(fGpu)->resourceAccess().insertResource(this); get_resource_cache(fGpu)->resourceAccess().insertResource(this);
} }
void GrGpuResource::detachFromCache() {
if (this->wasDestroyed()) {
return;
}
if (fUniqueKey.isValid()) {
this->removeUniqueKey();
}
this->removeScratchKey();
this->makeUnbudgeted();
}
GrGpuResource::~GrGpuResource() { GrGpuResource::~GrGpuResource() {
// The cache should have released or destroyed this resource. // The cache should have released or destroyed this resource.
SkASSERT(this->wasDestroyed()); SkASSERT(this->wasDestroyed());

View File

@ -8,7 +8,6 @@
#ifndef GrTexturePriv_DEFINED #ifndef GrTexturePriv_DEFINED
#define GrTexturePriv_DEFINED #define GrTexturePriv_DEFINED
#include "GrExternalTextureData.h"
#include "GrTexture.h" #include "GrTexture.h"
/** Class that adds methods to GrTexture that are only intended for use internal to Skia. /** Class that adds methods to GrTexture that are only intended for use internal to Skia.
@ -68,15 +67,6 @@ public:
} }
SkDestinationSurfaceColorMode mipColorMode() const { return fTexture->fMipColorMode; } SkDestinationSurfaceColorMode mipColorMode() const { return fTexture->fMipColorMode; }
/**
* Return the native bookkeeping data for this texture, and detach the backend object from
* this GrTexture. It's lifetime will no longer be managed by Ganesh, and this GrTexture will
* no longer refer to it. Leaves this GrTexture in an orphan state.
*/
std::unique_ptr<GrExternalTextureData> detachBackendTexture() {
return fTexture->detachBackendTexture();
}
static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*); static void ComputeScratchKey(const GrSurfaceDesc&, GrScratchKey*);
private: private:

View File

@ -4741,7 +4741,3 @@ bool GrGLGpu::waitFence(GrFence fence, uint64_t timeout) const {
void GrGLGpu::deleteFence(GrFence fence) const { void GrGLGpu::deleteFence(GrFence fence) const {
GL_CALL(DeleteSync((GrGLsync)fence)); GL_CALL(DeleteSync((GrGLsync)fence));
} }
void GrGLGpu::flush() {
GL_CALL(Flush());
}

View File

@ -150,8 +150,6 @@ public:
bool waitFence(GrFence, uint64_t timeout) const override; bool waitFence(GrFence, uint64_t timeout) const override;
void deleteFence(GrFence) const override; void deleteFence(GrFence) const override;
void flush() override;
private: private:
GrGLGpu(GrGLContext* ctx, GrContext* context); GrGLGpu(GrGLContext* ctx, GrContext* context);

View File

@ -5,11 +5,9 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "GrContext.h"
#include "GrGLTexture.h" #include "GrGLTexture.h"
#include "GrGLGpu.h" #include "GrGLGpu.h"
#include "GrShaderCaps.h" #include "GrShaderCaps.h"
#include "SkMakeUnique.h"
#include "SkTraceMemoryDump.h" #include "SkTraceMemoryDump.h"
#define GPUGL static_cast<GrGLGpu*>(this->getGpu()) #define GPUGL static_cast<GrGLGpu*>(this->getGpu())
@ -113,23 +111,6 @@ GrBackendObject GrGLTexture::getTextureHandle() const {
return reinterpret_cast<GrBackendObject>(&fInfo); return reinterpret_cast<GrBackendObject>(&fInfo);
} }
std::unique_ptr<GrExternalTextureData> GrGLTexture::detachBackendTexture() {
// Flush any pending writes to this texture, as well GL itself
GrFence fence = this->getContext()->prepareSurfaceForExternalIOAndFlush(this);
// Make a copy of our GL-specific information
auto data = skstd::make_unique<GrGLExternalTextureData>(fInfo, fence);
// Ensure the cache can't reach this texture anymore
this->detachFromCache();
// Detach from the GL object, so we don't use it (or try to delete it when we're freed)
fInfo.fTarget = 0;
fInfo.fID = 0;
return std::move(data);
}
void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
const SkString& dumpName) const { const SkString& dumpName) const {
SkString texture_id; SkString texture_id;

View File

@ -71,7 +71,6 @@ protected:
void onRelease() override; void onRelease() override;
void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump, void setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
const SkString& dumpName) const override; const SkString& dumpName) const override;
std::unique_ptr<GrExternalTextureData> detachBackendTexture() override;
private: private:
TexParams fTexParams; TexParams fTexParams;

View File

@ -1860,6 +1860,3 @@ void GrVkGpu::deleteFence(GrFence fence) const {
GR_VK_CALL(this->vkInterface(), DestroyFence(this->device(), (VkFence)fence, nullptr)); GR_VK_CALL(this->vkInterface(), DestroyFence(this->device(), (VkFence)fence, nullptr));
} }
void GrVkGpu::flush() {
// We submit the command buffer to the queue whenever Ganesh is flushed, so nothing is needed
}

View File

@ -133,8 +133,6 @@ public:
bool waitFence(GrFence, uint64_t timeout) const override; bool waitFence(GrFence, uint64_t timeout) const override;
void deleteFence(GrFence) const override; void deleteFence(GrFence) const override;
void flush() override;
void generateMipmap(GrVkTexture* tex); void generateMipmap(GrVkTexture* tex);
bool updateBuffer(GrVkBuffer* buffer, const void* src, VkDeviceSize offset, VkDeviceSize size); bool updateBuffer(GrVkBuffer* buffer, const void* src, VkDeviceSize offset, VkDeviceSize size);

View File

@ -144,12 +144,6 @@ GrBackendObject GrVkTexture::getTextureHandle() const {
return (GrBackendObject)&fInfo; return (GrBackendObject)&fInfo;
} }
std::unique_ptr<GrExternalTextureData> GrVkTexture::detachBackendTexture() {
// Not supported on Vulkan yet
// TODO: Add thread-safe memory pools, and implement this.
return nullptr;
}
GrVkGpu* GrVkTexture::getVkGpu() const { GrVkGpu* GrVkTexture::getVkGpu() const {
SkASSERT(!this->wasDestroyed()); SkASSERT(!this->wasDestroyed());
return static_cast<GrVkGpu*>(this->getGpu()); return static_cast<GrVkGpu*>(this->getGpu());

View File

@ -42,7 +42,6 @@ protected:
void onAbandon() override; void onAbandon() override;
void onRelease() override; void onRelease() override;
std::unique_ptr<GrExternalTextureData> detachBackendTexture() override;
private: private:
enum Wrapped { kWrapped }; enum Wrapped { kWrapped };

View File

@ -8,7 +8,6 @@
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkBitmapCache.h" #include "SkBitmapCache.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkCrossContextImageData.h"
#include "SkData.h" #include "SkData.h"
#include "SkImageEncoder.h" #include "SkImageEncoder.h"
#include "SkImageFilter.h" #include "SkImageFilter.h"
@ -358,21 +357,6 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, SkColorSpace* dstColorSpace
return nullptr; return nullptr;
} }
std::unique_ptr<SkCrossContextImageData> SkCrossContextImageData::MakeFromEncoded(
GrContext*, sk_sp<SkData> encoded, SkColorSpace* dstColorSpace) {
sk_sp<SkImage> image = SkImage::MakeFromEncoded(std::move(encoded));
if (!image) {
return nullptr;
}
// TODO: Force decode to raster here?
return std::unique_ptr<SkCrossContextImageData>(new SkCrossContextImageData(std::move(image)));
}
sk_sp<SkImage> SkImage::MakeFromCrossContextImageData(
GrContext*, std::unique_ptr<SkCrossContextImageData> ccid) {
return ccid->fImage;
}
sk_sp<SkImage> SkImage::makeNonTextureImage() const { sk_sp<SkImage> SkImage::makeNonTextureImage() const {
return sk_ref_sp(const_cast<SkImage*>(this)); return sk_ref_sp(const_cast<SkImage*>(this));
} }

View File

@ -14,7 +14,6 @@
#include "GrCaps.h" #include "GrCaps.h"
#include "GrContext.h" #include "GrContext.h"
#include "GrContextPriv.h" #include "GrContextPriv.h"
#include "GrGpu.h"
#include "GrImageTextureMaker.h" #include "GrImageTextureMaker.h"
#include "GrRenderTargetContext.h" #include "GrRenderTargetContext.h"
#include "GrTextureAdjuster.h" #include "GrTextureAdjuster.h"
@ -22,7 +21,6 @@
#include "GrTextureProxy.h" #include "GrTextureProxy.h"
#include "effects/GrYUVEffect.h" #include "effects/GrYUVEffect.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkCrossContextImageData.h"
#include "SkBitmapCache.h" #include "SkBitmapCache.h"
#include "SkGrPriv.h" #include "SkGrPriv.h"
#include "SkImage_Gpu.h" #include "SkImage_Gpu.h"
@ -379,70 +377,6 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrContext* context, SkColorSpace* dstCo
return nullptr; return nullptr;
} }
std::unique_ptr<SkCrossContextImageData> SkCrossContextImageData::MakeFromEncoded(
GrContext* context, sk_sp<SkData> encoded, SkColorSpace* dstColorSpace) {
sk_sp<SkImage> codecImage = SkImage::MakeFromEncoded(std::move(encoded));
if (!codecImage) {
return nullptr;
}
// If we don't have the ability to use fences, we can't safely transfer a texture between
// threads, so just hand off the codec image
if (!context->caps()->fenceSyncSupport()) {
return std::unique_ptr<SkCrossContextImageData>(
new SkCrossContextImageData(std::move(codecImage)));
}
sk_sp<SkImage> textureImage = codecImage->makeTextureImage(context, dstColorSpace);
if (!textureImage) {
// TODO: Force decode to raster here? Do mip-mapping, like getDeferredTextureImageData?
return std::unique_ptr<SkCrossContextImageData>(
new SkCrossContextImageData(std::move(codecImage)));
}
// Crack open the gpu image, extract the backend data, stick it in the SkCCID
GrTexture* texture = as_IB(textureImage)->peekTexture();
SkASSERT(texture);
GrBackendTextureDesc desc;
desc.fFlags = kNone_GrBackendTextureFlag;
desc.fOrigin = texture->origin();
desc.fWidth = texture->width();
desc.fHeight = texture->height();
desc.fConfig = texture->config();
desc.fSampleCnt = 0;
auto textureData = texture->texturePriv().detachBackendTexture();
if (!textureData) {
// Handles backends that don't support this feature (currently Vulkan). Do a raster decode
// here?
return std::unique_ptr<SkCrossContextImageData>(
new SkCrossContextImageData(std::move(codecImage)));
}
SkImageInfo info = as_IB(textureImage)->onImageInfo();
return std::unique_ptr<SkCrossContextImageData>(new SkCrossContextImageData(
desc, std::move(textureData), info.alphaType(), info.refColorSpace()));
}
sk_sp<SkImage> SkImage::MakeFromCrossContextImageData(
GrContext* context, std::unique_ptr<SkCrossContextImageData> ccid) {
if (ccid->fImage) {
// No pre-existing GPU resource. We could upload it now (with makeTextureImage),
// but we'd need a dstColorSpace.
return ccid->fImage;
}
if (ccid->fTextureData) {
GrFence fence = ccid->fTextureData->getFence();
context->getGpu()->waitFence(fence);
context->getGpu()->deleteFence(fence);
}
return MakeFromAdoptedTexture(context, ccid->fDesc, ccid->fAlphaType,
std::move(ccid->fColorSpace));
}
sk_sp<SkImage> SkImage::makeNonTextureImage() const { sk_sp<SkImage> SkImage::makeNonTextureImage() const {
if (!this->isTextureBacked()) { if (!this->isTextureBacked()) {
return sk_ref_sp(const_cast<SkImage*>(this)); return sk_ref_sp(const_cast<SkImage*>(this));

View File

@ -1,218 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkTypes.h"
#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "Resources.h"
#include "SkAutoPixmapStorage.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkCrossContextImageData.h"
#include "SkSemaphore.h"
#include "SkSurface.h"
#include "SkThreadUtils.h"
#include "Test.h"
using namespace sk_gpu_test;
static SkImageInfo read_pixels_info(SkImage* image) {
return SkImageInfo::MakeN32(image->width(), image->height(), image->alphaType());
}
static bool colors_are_close(SkColor a, SkColor b, int error) {
return SkTAbs((int)SkColorGetR(a) - (int)SkColorGetR(b)) <= error &&
SkTAbs((int)SkColorGetG(a) - (int)SkColorGetG(b)) <= error &&
SkTAbs((int)SkColorGetB(a) - (int)SkColorGetB(b)) <= error;
}
static void assert_equal(skiatest::Reporter* reporter, SkImage* a, SkImage* b, int error) {
REPORTER_ASSERT(reporter, a->width() == b->width());
REPORTER_ASSERT(reporter, a->height() == b->height());
SkAutoPixmapStorage pmapA, pmapB;
pmapA.alloc(read_pixels_info(a));
pmapB.alloc(read_pixels_info(b));
REPORTER_ASSERT(reporter, a->readPixels(pmapA, 0, 0));
REPORTER_ASSERT(reporter, b->readPixels(pmapB, 0, 0));
for (int y = 0; y < a->height(); ++y) {
for (int x = 0; x < a->width(); ++x) {
SkColor ca = pmapA.getColor(x, y);
SkColor cb = pmapB.getColor(x, y);
if (!error) {
if (ca != cb) {
ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d)", ca, cb, x, y);
return;
}
} else {
if (!colors_are_close(ca, cb, error)) {
ERRORF(reporter, "Expected 0x%08x +-%d but got 0x%08x at (%d, %d)",
ca, error, cb, x, y);
return;
}
}
}
}
}
static void draw_image_test_pattern(SkCanvas* canvas) {
canvas->clear(SK_ColorWHITE);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
canvas->drawRect(SkRect::MakeXYWH(5, 5, 10, 10), paint);
}
static sk_sp<SkImage> create_test_image() {
SkBitmap bm;
bm.allocN32Pixels(20, 20, true);
SkCanvas canvas(bm);
draw_image_test_pattern(&canvas);
return SkImage::MakeFromBitmap(bm);
}
static sk_sp<SkData> create_test_data(SkEncodedImageFormat format) {
auto image = create_test_image();
return sk_sp<SkData>(image->encode(format, 100));
}
DEF_GPUTEST(CrossContextImage_SameContext, reporter, /*factory*/) {
GrContextFactory factory;
sk_sp<SkImage> testImage = create_test_image();
// Test both PNG and JPG, to exercise GPU YUV conversion
for (auto format : { SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG }) {
sk_sp<SkData> encoded = create_test_data(format);
for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
if (!sk_gpu_test::GrContextFactory::IsRenderingContext(ctxType)) {
continue;
}
ContextInfo info = factory.getContextInfo(ctxType);
if (!info.grContext()) {
continue;
}
auto ccid = SkCrossContextImageData::MakeFromEncoded(info.grContext(), encoded,
nullptr);
REPORTER_ASSERT(reporter, ccid != nullptr);
auto image = SkImage::MakeFromCrossContextImageData(info.grContext(), std::move(ccid));
REPORTER_ASSERT(reporter, image != nullptr);
// JPEG encode -> decode won't round trip the image perfectly
assert_equal(reporter, testImage.get(), image.get(),
SkEncodedImageFormat::kJPEG == format ? 2 : 0);
}
}
}
DEF_GPUTEST(CrossContextImage_SharedContextSameThread, reporter, /*factory*/) {
GrContextFactory factory;
sk_sp<SkImage> testImage = create_test_image();
// Test both PNG and JPG, to exercise GPU YUV conversion
for (auto format : { SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG }) {
sk_sp<SkData> encoded = create_test_data(format);
for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
if (!sk_gpu_test::GrContextFactory::IsRenderingContext(ctxType)) {
continue;
}
ContextInfo info = factory.getContextInfo(ctxType);
if (!info.grContext()) {
continue;
}
auto ccid = SkCrossContextImageData::MakeFromEncoded(info.grContext(), encoded,
nullptr);
REPORTER_ASSERT(reporter, ccid != nullptr);
ContextInfo info2 = factory.getSharedContextInfo(info.grContext());
auto image = SkImage::MakeFromCrossContextImageData(info2.grContext(), std::move(ccid));
REPORTER_ASSERT(reporter, image != nullptr);
// JPEG encode -> decode won't round trip the image perfectly
assert_equal(reporter, testImage.get(), image.get(),
SkEncodedImageFormat::kJPEG == format ? 2 : 0);
}
}
}
namespace {
struct CrossContextImage_ThreadContext {
GrContext* fGrContext;
sk_gpu_test::TestContext* fTestContext;
SkSemaphore fSemaphore;
std::unique_ptr<SkCrossContextImageData> fCCID;
sk_sp<SkData> fEncoded;
};
}
static void upload_image_thread_proc(void* data) {
CrossContextImage_ThreadContext* ctx = static_cast<CrossContextImage_ThreadContext*>(data);
ctx->fTestContext->makeCurrent();
ctx->fCCID = SkCrossContextImageData::MakeFromEncoded(ctx->fGrContext, ctx->fEncoded, nullptr);
ctx->fSemaphore.signal();
}
DEF_GPUTEST(CrossContextImage_SharedContextOtherThread, reporter, /*factory*/) {
GrContextFactory factory;
sk_sp<SkImage> testImage = create_test_image();
// Test both PNG and JPG, to exercise GPU YUV conversion
for (auto format : { SkEncodedImageFormat::kPNG, SkEncodedImageFormat::kJPEG }) {
sk_sp<SkData> encoded = create_test_data(format);
for (int i = 0; i < GrContextFactory::kContextTypeCnt; ++i) {
GrContextFactory::ContextType ctxType = static_cast<GrContextFactory::ContextType>(i);
if (!sk_gpu_test::GrContextFactory::IsRenderingContext(ctxType)) {
continue;
}
// Create two GrContexts in a share group
ContextInfo info = factory.getContextInfo(ctxType);
if (!info.grContext()) {
continue;
}
ContextInfo info2 = factory.getSharedContextInfo(info.grContext());
if (!info2.grContext()) {
continue;
}
// Make the first one current (on this thread) again
info.testContext()->makeCurrent();
// Bundle up data for the worker thread
CrossContextImage_ThreadContext ctx;
ctx.fGrContext = info2.grContext();
ctx.fTestContext = info2.testContext();
ctx.fEncoded = encoded;
SkThread uploadThread(upload_image_thread_proc, &ctx);
SkAssertResult(uploadThread.start());
ctx.fSemaphore.wait();
auto image = SkImage::MakeFromCrossContextImageData(info.grContext(),
std::move(ctx.fCCID));
REPORTER_ASSERT(reporter, image != nullptr);
// JPEG encode -> decode won't round trip the image perfectly
assert_equal(reporter, testImage.get(), image.get(),
SkEncodedImageFormat::kJPEG == format ? 2 : 0);
}
}
}
#endif

View File

@ -273,16 +273,4 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides
return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext); return ContextInfo(context.fBackend, context.fTestContext, context.fGrContext);
} }
ContextInfo GrContextFactory::getSharedContextInfo(GrContext* shareContext, uint32_t shareIndex) {
SkASSERT(shareContext);
for (int i = 0; i < fContexts.count(); ++i) {
if (!fContexts[i].fAbandoned && fContexts[i].fGrContext == shareContext) {
return this->getContextInfo(fContexts[i].fType, fContexts[i].fOverrides,
shareContext, shareIndex);
}
}
return ContextInfo();
}
} // namespace sk_gpu_test } // namespace sk_gpu_test

View File

@ -151,11 +151,6 @@ public:
ContextInfo getContextInfo(ContextType type, ContextInfo getContextInfo(ContextType type,
ContextOverrides overrides = ContextOverrides::kNone, ContextOverrides overrides = ContextOverrides::kNone,
GrContext* shareContext = nullptr, uint32_t shareIndex = 0); GrContext* shareContext = nullptr, uint32_t shareIndex = 0);
/**
* Get a context in the same share group as the passed in GrContext, with the same type and
* overrides.
*/
ContextInfo getSharedContextInfo(GrContext* shareContext, uint32_t shareIndex = 0);
/** /**
* Get a GrContext initialized with a type of GL context. It also makes the GL context current. * Get a GrContext initialized with a type of GL context. It also makes the GL context current.
*/ */

View File

@ -313,7 +313,6 @@ public:
GrFence SK_WARN_UNUSED_RESULT insertFence() const override { return 0; } GrFence SK_WARN_UNUSED_RESULT insertFence() const override { return 0; }
bool waitFence(GrFence, uint64_t) const override { return true; } bool waitFence(GrFence, uint64_t) const override { return true; }
void deleteFence(GrFence) const override {} void deleteFence(GrFence) const override {}
void flush() override {}
private: private:
void onResetContext(uint32_t resetBits) override {} void onResetContext(uint32_t resetBits) override {}

View File

@ -85,11 +85,7 @@ WinGLTestContext::WinGLTestContext(GrGLStandard forcedGpuAPI, WinGLTestContext*
kGLES_GrGLStandard == forcedGpuAPI ? kGLES_GrGLStandard == forcedGpuAPI ?
kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest; kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest;
HGLRC winShareContext = nullptr; HGLRC winShareContext = shareContext ? shareContext->fGlRenderContext : nullptr;
if (shareContext) {
winShareContext = shareContext->fPbufferContext ? shareContext->fPbufferContext->getGLRC()
: shareContext->fGlRenderContext;
}
fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType, winShareContext); fPbufferContext = SkWGLPbufferContext::Create(fDeviceContext, 0, contextType, winShareContext);
HDC dc; HDC dc;