aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrLayerHoister.cpp2
-rw-r--r--src/gpu/GrSurface.cpp4
-rw-r--r--src/gpu/GrSurfacePriv.h6
-rw-r--r--src/gpu/SkGpuDevice.cpp90
-rw-r--r--src/gpu/SkGpuDevice.h20
-rw-r--r--src/image/SkImage_Gpu.cpp2
-rw-r--r--src/image/SkSurface_Gpu.cpp8
7 files changed, 90 insertions, 42 deletions
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp
index 1f01e1a983..e1aa72c83d 100644
--- a/src/gpu/GrLayerHoister.cpp
+++ b/src/gpu/GrLayerHoister.cpp
@@ -281,7 +281,7 @@ SkBitmap wrap_texture(GrTexture* texture) {
SkASSERT(texture);
SkBitmap result;
- result.setInfo(texture->surfacePriv().info());
+ result.setInfo(texture->surfacePriv().info(kPremul_SkAlphaType));
result.setPixelRef(SkNEW_ARGS(SkGrPixelRef, (result.info(), texture)))->unref();
return result;
}
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index c052a235f0..b304ccb1dd 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -41,13 +41,13 @@ bool GrSurface::readPixels(int left, int top, int width, int height,
return false;
}
-SkImageInfo GrSurface::info() const {
+SkImageInfo GrSurface::info(SkAlphaType alphaType) const {
SkColorType colorType;
SkColorProfileType profileType;
if (!GrPixelConfig2ColorAndProfileType(this->config(), &colorType, &profileType)) {
sk_throw();
}
- return SkImageInfo::Make(this->width(), this->height(), colorType, kPremul_SkAlphaType,
+ return SkImageInfo::Make(this->width(), this->height(), colorType, alphaType,
profileType);
}
diff --git a/src/gpu/GrSurfacePriv.h b/src/gpu/GrSurfacePriv.h
index cd1f6b92ba..47bd44f4ef 100644
--- a/src/gpu/GrSurfacePriv.h
+++ b/src/gpu/GrSurfacePriv.h
@@ -18,10 +18,10 @@
class GrSurfacePriv {
public:
/**
- * Derive a SkImageInfo from the surface's descriptor. This is lossy as ImageInfo has fields not
- * known to GrSurface (e.g. alphaType).
+ * Derive a SkImageInfo from the surface's descriptor. The caller must provide the alpha type as
+ * GrSurface has no equivalent.
*/
- SkImageInfo info() const { return fSurface->info(); }
+ SkImageInfo info(SkAlphaType alphaType) const { return fSurface->info(alphaType); }
/**
* Write the contents of the surface to a PNG. Returns true if successful.
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 1603cd64f1..d0f8d46ee8 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -122,18 +122,61 @@ public:
///////////////////////////////////////////////////////////////////////////////
-SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props, unsigned flags) {
- return SkGpuDevice::Create(rt, rt->width(), rt->height(), props, flags);
+/** Checks that the alpha type is legal and gets constructor flags. Returns false if device creation
+ should fail. */
+bool SkGpuDevice::CheckAlphaTypeAndGetFlags(
+ const SkImageInfo* info, SkGpuDevice::InitContents init, unsigned* flags) {
+ *flags = 0;
+ if (info) {
+ switch (info->alphaType()) {
+ case kPremul_SkAlphaType:
+ break;
+ case kOpaque_SkAlphaType:
+ *flags |= SkGpuDevice::kIsOpaque_Flag;
+ break;
+ default: // If it is unpremul or unknown don't try to render
+ return false;
+ }
+ }
+ if (kClear_InitContents == init) {
+ *flags |= kNeedClear_Flag;
+ }
+ return true;
+}
+
+SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, const SkSurfaceProps* props,
+ InitContents init) {
+ return SkGpuDevice::Create(rt, rt->width(), rt->height(), props, init);
}
SkGpuDevice* SkGpuDevice::Create(GrRenderTarget* rt, int width, int height,
- const SkSurfaceProps* props, unsigned flags) {
+ const SkSurfaceProps* props, InitContents init) {
if (!rt || rt->wasDestroyed()) {
return NULL;
}
+ unsigned flags;
+ if (!CheckAlphaTypeAndGetFlags(NULL, init, &flags)) {
+ return NULL;
+ }
return SkNEW_ARGS(SkGpuDevice, (rt, width, height, props, flags));
}
+SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgeted,
+ const SkImageInfo& info, int sampleCount,
+ const SkSurfaceProps* props, InitContents init) {
+ unsigned flags;
+ if (!CheckAlphaTypeAndGetFlags(&info, init, &flags)) {
+ return NULL;
+ }
+
+ SkAutoTUnref<GrRenderTarget> rt(CreateRenderTarget(context, budgeted, info, sampleCount));
+ if (NULL == rt) {
+ return NULL;
+ }
+
+ return SkNEW_ARGS(SkGpuDevice, (rt, info.width(), info.height(), props, flags));
+}
+
SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
const SkSurfaceProps* props, unsigned flags)
: INHERITED(SkSurfacePropsCopyOrDefault(props))
@@ -141,11 +184,13 @@ SkGpuDevice::SkGpuDevice(GrRenderTarget* rt, int width, int height,
fDrawProcs = NULL;
fContext = SkRef(rt->getContext());
- fNeedClear = flags & kNeedClear_Flag;
+ fNeedClear = SkToBool(flags & kNeedClear_Flag);
+ fOpaque = SkToBool(flags & kIsOpaque_Flag);
fRenderTarget = SkRef(rt);
- SkImageInfo info = rt->surfacePriv().info().makeWH(width, height);
+ SkAlphaType at = fOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+ SkImageInfo info = rt->surfacePriv().info(at).makeWH(width, height);
SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (info, rt));
fLegacyBitmap.setInfo(info);
fLegacyBitmap.setPixelRef(pr)->unref();
@@ -192,18 +237,6 @@ GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::B
return texture->asRenderTarget();
}
-SkGpuDevice* SkGpuDevice::Create(GrContext* context, SkSurface::Budgeted budgeted,
- const SkImageInfo& info, int sampleCount,
- const SkSurfaceProps* props, unsigned flags) {
-
- SkAutoTUnref<GrRenderTarget> rt(CreateRenderTarget(context, budgeted, info, sampleCount));
- if (NULL == rt) {
- return NULL;
- }
-
- return SkNEW_ARGS(SkGpuDevice, (rt, info.width(), info.height(), props, flags));
-}
-
SkGpuDevice::~SkGpuDevice() {
if (fDrawProcs) {
delete fDrawProcs;
@@ -229,8 +262,8 @@ bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size
if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
flags = GrContext::kUnpremul_PixelOpsFlag;
}
- return fContext->readRenderTargetPixels(fRenderTarget, x, y, dstInfo.width(), dstInfo.height(),
- config, dstPixels, dstRowBytes, flags);
+ return fRenderTarget->readPixels(x, y, dstInfo.width(), dstInfo.height(), config, dstPixels,
+ dstRowBytes, flags);
}
bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
@@ -331,8 +364,12 @@ void SkGpuDevice::replaceRenderTarget(bool shouldRetainContent) {
fRenderTarget->unref();
fRenderTarget = newRT.detach();
- SkASSERT(fRenderTarget->surfacePriv().info() == fLegacyBitmap.info());
- SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
+#ifdef SK_DEBUG
+ SkImageInfo info = fRenderTarget->surfacePriv().info(fOpaque ? kOpaque_SkAlphaType :
+ kPremul_SkAlphaType);
+ SkASSERT(info == fLegacyBitmap.info());
+#endif
+ SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fLegacyBitmap.info(), fRenderTarget));
fLegacyBitmap.setPixelRef(pr)->unref();
fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext(&this->surfaceProps())));
@@ -662,8 +699,7 @@ static int determine_tile_size(const SkBitmap& bitmap, const SkIRect& src, int m
// Given a bitmap, an optional src rect, and a context with a clip and matrix determine what
// pixels from the bitmap are necessary.
-static void determine_clipped_src_rect(const GrContext* context,
- const GrRenderTarget* rt,
+static void determine_clipped_src_rect(const GrRenderTarget* rt,
const GrClip& clip,
const SkMatrix& viewMatrix,
const SkBitmap& bitmap,
@@ -706,7 +742,7 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
// if it's larger than the max tile size, then we have no choice but tiling.
if (bitmap.width() > maxTileSize || bitmap.height() > maxTileSize) {
- determine_clipped_src_rect(fContext, fRenderTarget, fClip, viewMatrix, bitmap,
+ determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap,
srcRectPtr, clippedSrcRect);
*tileSize = determine_tile_size(bitmap, *clippedSrcRect, maxTileSize);
return true;
@@ -736,7 +772,7 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
}
// Figure out how much of the src we will need based on the src rect and clipping.
- determine_clipped_src_rect(fContext, fRenderTarget, fClip, viewMatrix, bitmap, srcRectPtr,
+ determine_clipped_src_rect(fRenderTarget, fClip, viewMatrix, bitmap, srcRectPtr,
clippedSrcRect);
*tileSize = kBmpSmallTileSize; // already know whole bitmap fits in one max sized tile.
size_t usedTileBytes = get_tile_count(*clippedSrcRect, kBmpSmallTileSize) *
@@ -1672,7 +1708,7 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
SkAutoTUnref<GrTexture> texture;
// Skia's convention is to only clear a device if it is non-opaque.
- unsigned flags = cinfo.fInfo.isOpaque() ? 0 : kNeedClear_Flag;
+ InitContents init = cinfo.fInfo.isOpaque() ? kUninit_InitContents : kClear_InitContents;
// layers are never draw in repeat modes, so we can request an approx
// match and ignore any padding.
@@ -1684,7 +1720,7 @@ SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
if (texture) {
SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry);
return SkGpuDevice::Create(
- texture->asRenderTarget(), cinfo.fInfo.width(), cinfo.fInfo.height(), &props, flags);
+ texture->asRenderTarget(), cinfo.fInfo.width(), cinfo.fInfo.height(), &props, init);
} else {
SkErrorInternals::SetError( kInternalError_SkError,
"---- failed to create gpu device texture [%d %d]\n",
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index f71450d7c9..9fa756c29a 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -30,21 +30,22 @@ struct GrCachedLayer;
*/
class SK_API SkGpuDevice : public SkBaseDevice {
public:
- enum Flags {
- kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear
+ enum InitContents {
+ kClear_InitContents,
+ kUninit_InitContents
};
/**
* Creates an SkGpuDevice from a GrRenderTarget.
*/
- static SkGpuDevice* Create(GrRenderTarget* target, const SkSurfaceProps*, unsigned flags = 0);
+ static SkGpuDevice* Create(GrRenderTarget* target, const SkSurfaceProps*, InitContents);
/**
* Creates an SkGpuDevice from a GrRenderTarget whose texture width/height is
* different than its actual width/height (e.g., approx-match scratch texture).
*/
static SkGpuDevice* Create(GrRenderTarget* target, int width, int height,
- const SkSurfaceProps*, unsigned flags = 0);
+ const SkSurfaceProps*, InitContents);
/**
* New device that will create an offscreen renderTarget based on the ImageInfo and
@@ -52,7 +53,7 @@ public:
* the resource cache budget. On failure, returns NULL.
*/
static SkGpuDevice* Create(GrContext*, SkSurface::Budgeted, const SkImageInfo&,
- int sampleCount, const SkSurfaceProps*, unsigned flags = 0);
+ int sampleCount, const SkSurfaceProps*, InitContents);
virtual ~SkGpuDevice();
@@ -153,6 +154,15 @@ private:
// remove when our clients don't rely on accessBitmap()
SkBitmap fLegacyBitmap;
bool fNeedClear;
+ bool fOpaque;
+
+ enum Flags {
+ kNeedClear_Flag = 1 << 0, //!< Surface requires an initial clear
+ kIsOpaque_Flag = 1 << 1, //!< Hint from client that rendering to this device will be
+ // opaque even if the config supports alpha.
+ };
+ static bool CheckAlphaTypeAndGetFlags(const SkImageInfo* info, InitContents init,
+ unsigned* flags);
SkGpuDevice(GrRenderTarget*, int width, int height, const SkSurfaceProps*, unsigned flags);
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 973f4ba304..4003631c8a 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -61,7 +61,7 @@ bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
}
bool SkImage_Gpu::isOpaque() const {
- return GrPixelConfigIsOpaque(fTexture->config());
+ return GrPixelConfigIsOpaque(fTexture->config()) || fAlphaType == kOpaque_SkAlphaType;
}
static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes) {
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index cbc183eacf..fa006a61cd 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -83,7 +83,8 @@ void SkSurface_Gpu::onDiscard() {
///////////////////////////////////////////////////////////////////////////////
SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurfaceProps* props) {
- SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(target, props));
+ SkAutoTUnref<SkGpuDevice> device(
+ SkGpuDevice::Create(target, props, SkGpuDevice::kUninit_InitContents));
if (!device) {
return NULL;
}
@@ -93,7 +94,7 @@ SkSurface* SkSurface::NewRenderTargetDirect(GrRenderTarget* target, const SkSurf
SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, Budgeted budgeted, const SkImageInfo& info,
int sampleCount, const SkSurfaceProps* props) {
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(ctx, budgeted, info, sampleCount, props,
- SkGpuDevice::kNeedClear_Flag));
+ SkGpuDevice::kClear_InitContents));
if (!device) {
return NULL;
}
@@ -113,7 +114,8 @@ SkSurface* SkSurface::NewWrappedRenderTarget(GrContext* context, GrBackendTextur
if (!surface) {
return NULL;
}
- SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props));
+ SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(surface->asRenderTarget(), props,
+ SkGpuDevice::kUninit_InitContents));
if (!device) {
return NULL;
}