2012-07-27 21:10:42 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2012 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SkSurface_DEFINED
|
|
|
|
#define SkSurface_DEFINED
|
|
|
|
|
|
|
|
#include "SkRefCnt.h"
|
|
|
|
#include "SkImage.h"
|
2014-09-22 14:29:03 +00:00
|
|
|
#include "SkSurfaceProps.h"
|
2012-07-27 21:10:42 +00:00
|
|
|
|
|
|
|
class SkCanvas;
|
|
|
|
class SkPaint;
|
2012-07-31 15:45:27 +00:00
|
|
|
class GrContext;
|
|
|
|
class GrRenderTarget;
|
2012-07-27 21:10:42 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SkSurface represents the backend/results of drawing to a canvas. For raster
|
|
|
|
* drawing, the surface will be pixels, but (for example) when drawing into
|
|
|
|
* a PDF or Picture canvas, the surface stores the recorded commands.
|
|
|
|
*
|
|
|
|
* To draw into a canvas, first create the appropriate type of Surface, and
|
|
|
|
* then request the canvas from the surface.
|
2014-12-31 20:31:43 +00:00
|
|
|
*
|
|
|
|
* SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
|
|
|
|
* of the requested dimensions are zero, then NULL will be returned.
|
2012-07-27 21:10:42 +00:00
|
|
|
*/
|
2013-04-18 13:28:19 +00:00
|
|
|
class SK_API SkSurface : public SkRefCnt {
|
2012-07-27 21:10:42 +00:00
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Create a new surface, using the specified pixels/rowbytes as its
|
|
|
|
* backend.
|
|
|
|
*
|
|
|
|
* If the requested surface cannot be created, or the request is not a
|
|
|
|
* supported configuration, NULL will be returned.
|
|
|
|
*/
|
2014-09-22 14:29:03 +00:00
|
|
|
static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
|
|
|
|
const SkSurfaceProps* = NULL);
|
2012-07-27 21:10:42 +00:00
|
|
|
|
2014-06-27 13:48:14 +00:00
|
|
|
/**
|
|
|
|
* The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
|
|
|
|
* when the surface is deleted, and is passed the pixel memory and the specified context.
|
|
|
|
*/
|
|
|
|
static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
|
|
|
|
void (*releaseProc)(void* pixels, void* context),
|
2014-09-22 14:29:03 +00:00
|
|
|
void* context, const SkSurfaceProps* = NULL);
|
2014-06-27 13:48:14 +00:00
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
/**
|
2016-01-30 18:01:06 +00:00
|
|
|
* Return a new surface, with the memory for the pixels automatically allocated, but respecting
|
|
|
|
* the specified rowBytes. If rowBytes==0, then a default value will be chosen. If a non-zero
|
|
|
|
* rowBytes is specified, then any images snapped off of this surface (via newImageSnapshot())
|
|
|
|
* are guaranteed to have the same rowBytes.
|
2012-07-27 21:10:42 +00:00
|
|
|
*
|
|
|
|
* If the requested surface cannot be created, or the request is not a
|
|
|
|
* supported configuration, NULL will be returned.
|
|
|
|
*/
|
2016-01-30 18:01:06 +00:00
|
|
|
static SkSurface* NewRaster(const SkImageInfo&, size_t rowBytes, const SkSurfaceProps*);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate a new surface, automatically computing the rowBytes.
|
|
|
|
*/
|
2014-09-22 14:29:03 +00:00
|
|
|
static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
|
2012-07-27 21:10:42 +00:00
|
|
|
|
2013-09-17 20:03:43 +00:00
|
|
|
/**
|
2013-11-01 13:46:54 +00:00
|
|
|
* Helper version of NewRaster. It creates a SkImageInfo with the
|
2013-09-17 20:03:43 +00:00
|
|
|
* specified width and height, and populates the rest of info to match
|
|
|
|
* pixels in SkPMColor format.
|
|
|
|
*/
|
2014-12-10 15:24:28 +00:00
|
|
|
static SkSurface* NewRasterN32Premul(int width, int height, const SkSurfaceProps* props = NULL) {
|
|
|
|
return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
|
|
|
|
}
|
2013-09-17 20:03:43 +00:00
|
|
|
|
2014-02-04 14:58:30 +00:00
|
|
|
/**
|
|
|
|
* Return a new surface using the specified render target.
|
|
|
|
*/
|
2014-09-22 14:29:03 +00:00
|
|
|
static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
|
2015-06-26 18:45:03 +00:00
|
|
|
|
2014-09-22 14:29:03 +00:00
|
|
|
static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
|
|
|
|
return NewRenderTargetDirect(target, NULL);
|
|
|
|
}
|
2015-04-08 15:38:40 +00:00
|
|
|
|
|
|
|
/**
|
2015-06-30 19:04:40 +00:00
|
|
|
* Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag
|
|
|
|
* must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
|
|
|
|
* of the texture and the client must ensure the texture is valid for the lifetime of the
|
|
|
|
* SkSurface.
|
2015-04-08 15:38:40 +00:00
|
|
|
*/
|
2015-06-30 19:04:40 +00:00
|
|
|
static SkSurface* NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
|
|
|
|
const SkSurfaceProps*);
|
|
|
|
// Legacy alias
|
|
|
|
static SkSurface* NewWrappedRenderTarget(GrContext* ctx, const GrBackendTextureDesc& desc,
|
|
|
|
const SkSurfaceProps* props) {
|
|
|
|
return NewFromBackendTexture(ctx, desc, props);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume
|
|
|
|
* ownership of the render target and the client must ensure the render target is valid for the
|
|
|
|
* lifetime of the SkSurface.
|
|
|
|
*/
|
|
|
|
static SkSurface* NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&,
|
|
|
|
const SkSurfaceProps*);
|
2015-06-26 18:45:03 +00:00
|
|
|
|
Add wrapBackendTextureAsRenderTarget API
Skia's GrTextureProvider currently exposes two APIs for wrapping backend
objects:
* wrapBackendTexture - wraps a texture into a GrTexture. Depending on
flags, this GrTexture can be converted to a GrRenderTarget. Skia
manages the render target objects it may create to provide a render
target for the texture. This allows Skia to create stencil buffers
if needed and manager MSAA resolves.
* wrapBackendRenderTarget - wraps a FBO into a GrRenderTarget. This
object cannot be converted to a GrTexture. Skia does not manage
the render target objects for such a GrRenderTarget, and as such
cannot attach stencil buffers or perform MSAA resolves on the
created GrRenderTarget.
Given these two options, wrapBackendTexture provides more versatility
and allows Skia more room for optimization. Chrome currently uses
wrapBackendTexture for this reason.
While these two functions cover most cases, they do not provide a way
for Skia to wrap a texture into a render target (and gain the MSAA and
stencil buffer management), without also creating a GrTexture. This is
problematic in cases where a texture can be bound to a render target,
but cannot be textured from, as is the case in Chrome's limited support
for GL_TEXTURE_RECTANGLE.
To address this, a new function is created:
* wrapBackendTextureAsRenderTarget - wraps a texture into a
GrRenderTarget. As with wrapBackendTexture, the created render
target objects are fully managed by Skia. Unlike wrapBackendTexture
no GrTexture is created, and the created object will never be
textured from.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1709163003
Review URL: https://codereview.chromium.org/1709163003
2016-02-24 22:49:51 +00:00
|
|
|
/**
|
|
|
|
* Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as
|
|
|
|
* a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own
|
|
|
|
* the associated render target objects (but not the provided texture). The kRenderTarget flag
|
|
|
|
* must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
|
|
|
|
* of the texture and the client must ensure the texture is valid for the lifetime of the
|
|
|
|
* SkSurface.
|
|
|
|
*/
|
|
|
|
static SkSurface* NewFromBackendTextureAsRenderTarget(
|
|
|
|
GrContext*, const GrBackendTextureDesc&, const SkSurfaceProps*);
|
|
|
|
|
2012-07-31 15:45:27 +00:00
|
|
|
/**
|
|
|
|
* Return a new surface whose contents will be drawn to an offscreen
|
|
|
|
* render target, allocated by the surface.
|
2016-02-11 00:32:34 +00:00
|
|
|
*
|
|
|
|
* The GrTextureStorageAllocator will be reused if SkImage snapshots create
|
|
|
|
* additional textures.
|
2012-07-31 15:45:27 +00:00
|
|
|
*/
|
2016-02-11 00:32:34 +00:00
|
|
|
static SkSurface* NewRenderTarget(
|
2016-02-25 16:33:02 +00:00
|
|
|
GrContext*, SkBudgeted, const SkImageInfo&, int sampleCount,
|
|
|
|
const SkSurfaceProps* = NULL, GrTextureStorageAllocator = GrTextureStorageAllocator());
|
2014-09-22 14:29:03 +00:00
|
|
|
|
2016-02-25 16:33:02 +00:00
|
|
|
static SkSurface* NewRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
|
2016-02-11 00:32:34 +00:00
|
|
|
return NewRenderTarget(gr, b, info, 0);
|
2014-09-22 14:29:03 +00:00
|
|
|
}
|
2012-07-31 15:45:27 +00:00
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
int width() const { return fWidth; }
|
|
|
|
int height() const { return fHeight; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a unique non-zero, unique value identifying the content of this
|
|
|
|
* surface. Each time the content is changed changed, either by drawing
|
|
|
|
* into this surface, or explicitly calling notifyContentChanged()) this
|
|
|
|
* method will return a new value.
|
|
|
|
*
|
|
|
|
* If this surface is empty (i.e. has a zero-dimention), this will return
|
|
|
|
* 0.
|
|
|
|
*/
|
2012-08-28 12:19:02 +00:00
|
|
|
uint32_t generationID();
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
/**
|
2013-04-22 14:28:01 +00:00
|
|
|
* Modes that can be passed to notifyContentWillChange
|
|
|
|
*/
|
|
|
|
enum ContentChangeMode {
|
2013-04-23 07:01:29 +00:00
|
|
|
/**
|
2013-04-22 14:28:01 +00:00
|
|
|
* Use this mode if it is known that the upcoming content changes will
|
|
|
|
* clear or overwrite prior contents, thus making them discardable.
|
|
|
|
*/
|
|
|
|
kDiscard_ContentChangeMode,
|
2013-04-23 07:01:29 +00:00
|
|
|
/**
|
2013-04-22 14:28:01 +00:00
|
|
|
* Use this mode if prior surface contents need to be preserved or
|
|
|
|
* if in doubt.
|
|
|
|
*/
|
|
|
|
kRetain_ContentChangeMode,
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call this if the contents are about to change. This will (lazily) force a new
|
2012-07-27 21:10:42 +00:00
|
|
|
* value to be returned from generationID() when it is called next.
|
2015-06-29 14:37:01 +00:00
|
|
|
*
|
|
|
|
* CAN WE DEPRECATE THIS?
|
2012-07-27 21:10:42 +00:00
|
|
|
*/
|
2013-04-22 14:28:01 +00:00
|
|
|
void notifyContentWillChange(ContentChangeMode mode);
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2015-07-08 19:54:04 +00:00
|
|
|
enum BackendHandleAccess {
|
|
|
|
kFlushRead_BackendHandleAccess, //!< caller may read from the backend object
|
|
|
|
kFlushWrite_BackendHandleAccess, //!< caller may write to the backend object
|
|
|
|
kDiscardWrite_BackendHandleAccess, //!< caller must over-write the entire backend object
|
2015-06-29 14:37:01 +00:00
|
|
|
};
|
2015-07-08 19:54:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* These are legacy aliases which will be removed soon
|
|
|
|
*/
|
|
|
|
static const BackendHandleAccess kFlushRead_TextureHandleAccess =
|
|
|
|
kFlushRead_BackendHandleAccess;
|
|
|
|
static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
|
|
|
|
kFlushWrite_BackendHandleAccess;
|
|
|
|
static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
|
|
|
|
kDiscardWrite_BackendHandleAccess;
|
|
|
|
|
|
|
|
|
2015-06-29 14:37:01 +00:00
|
|
|
/**
|
|
|
|
* Retrieves the backend API handle of the texture used by this surface, or 0 if the surface
|
|
|
|
* is not backed by a GPU texture.
|
|
|
|
*
|
|
|
|
* The returned texture-handle is only valid until the next draw-call into the surface,
|
|
|
|
* or the surface is deleted.
|
|
|
|
*/
|
2015-07-08 19:54:04 +00:00
|
|
|
GrBackendObject getTextureHandle(BackendHandleAccess);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the backend API handle of the RenderTarget backing this surface. Callers must
|
|
|
|
* ensure this function returns 'true' or else the GrBackendObject will be invalid
|
|
|
|
*
|
|
|
|
* In OpenGL this will return the FramebufferObject ID.
|
|
|
|
*/
|
|
|
|
bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess);
|
2015-06-29 14:37:01 +00:00
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
/**
|
2012-07-30 21:03:46 +00:00
|
|
|
* Return a canvas that will draw into this surface. This will always
|
|
|
|
* return the same canvas for a given surface, and is manged/owned by the
|
|
|
|
* surface. It should not be used when its parent surface has gone out of
|
|
|
|
* scope.
|
2012-07-27 21:10:42 +00:00
|
|
|
*/
|
2012-07-30 21:03:46 +00:00
|
|
|
SkCanvas* getCanvas();
|
2012-07-27 21:10:42 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a new surface that is "compatible" with this one, in that it will
|
|
|
|
* efficiently be able to be drawn into this surface. Typical calling
|
|
|
|
* pattern:
|
|
|
|
*
|
|
|
|
* SkSurface* A = SkSurface::New...();
|
|
|
|
* SkCanvas* canvasA = surfaceA->newCanvas();
|
|
|
|
* ...
|
|
|
|
* SkSurface* surfaceB = surfaceA->newSurface(...);
|
|
|
|
* SkCanvas* canvasB = surfaceB->newCanvas();
|
|
|
|
* ... // draw using canvasB
|
|
|
|
* canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
|
|
|
|
*/
|
2013-11-01 13:46:54 +00:00
|
|
|
SkSurface* newSurface(const SkImageInfo&);
|
2012-07-27 21:10:42 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an image of the current state of the surface pixels up to this
|
|
|
|
* point. Subsequent changes to the surface (by drawing into its canvas)
|
2015-01-23 16:08:04 +00:00
|
|
|
* will not be reflected in this image. If a copy must be made the Budgeted
|
|
|
|
* parameter controls whether it counts against the resource budget
|
|
|
|
* (currently for the gpu backend only).
|
2012-07-27 21:10:42 +00:00
|
|
|
*/
|
2016-02-25 16:33:02 +00:00
|
|
|
SkImage* newImageSnapshot(SkBudgeted = SkBudgeted::kYes);
|
2012-07-27 21:10:42 +00:00
|
|
|
|
2016-02-22 19:02:58 +00:00
|
|
|
/**
|
|
|
|
* In rare instances a client may want a unique copy of the SkSurface's contents in an image
|
|
|
|
* snapshot. This enum can be used to enforce that the image snapshot's backing store is not
|
|
|
|
* shared with another image snapshot or the surface's backing store. This is generally more
|
|
|
|
* expensive. This was added for Chromium bug 585250.
|
|
|
|
*/
|
|
|
|
enum ForceUnique {
|
|
|
|
kNo_ForceUnique,
|
|
|
|
kYes_ForceUnique
|
|
|
|
};
|
2016-02-25 16:33:02 +00:00
|
|
|
SkImage* newImageSnapshot(SkBudgeted, ForceUnique);
|
2016-02-22 19:02:58 +00:00
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
/**
|
2015-01-23 16:08:04 +00:00
|
|
|
* Though the caller could get a snapshot image explicitly, and draw that,
|
2012-07-27 21:10:42 +00:00
|
|
|
* it seems that directly drawing a surface into another canvas might be
|
|
|
|
* a common pattern, and that we could possibly be more efficient, since
|
|
|
|
* we'd know that the "snapshot" need only live until we've handed it off
|
|
|
|
* to the canvas.
|
|
|
|
*/
|
|
|
|
void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
|
|
|
|
|
2014-02-13 17:14:46 +00:00
|
|
|
/**
|
|
|
|
* If the surface has direct access to its pixels (i.e. they are in local
|
|
|
|
* RAM) return the const-address of those pixels, and if not null, return
|
|
|
|
* the ImageInfo and rowBytes. The returned address is only valid while
|
|
|
|
* the surface object is in scope, and no API call is made on the surface
|
|
|
|
* or its canvas.
|
|
|
|
*
|
|
|
|
* On failure, returns NULL and the info and rowBytes parameters are
|
|
|
|
* ignored.
|
|
|
|
*/
|
|
|
|
const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
|
|
|
|
|
2014-12-09 22:39:44 +00:00
|
|
|
/**
|
|
|
|
* Copy the pixels from the surface into the specified buffer (pixels + rowBytes),
|
2014-12-10 17:53:42 +00:00
|
|
|
* converting them into the requested format (dstInfo). The surface pixels are read
|
|
|
|
* starting at the specified (srcX,srcY) location.
|
2014-12-09 22:39:44 +00:00
|
|
|
*
|
|
|
|
* The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
|
|
|
|
*
|
|
|
|
* srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
|
|
|
|
*
|
|
|
|
* srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
|
|
|
|
* then we have two sets of pixels (of equal size). Replace the dst pixels with the
|
|
|
|
* corresponding src pixels, performing any colortype/alphatype transformations needed
|
|
|
|
* (in the case where the src and dst have different colortypes or alphatypes).
|
|
|
|
*
|
|
|
|
* This call can fail, returning false, for several reasons:
|
|
|
|
* - If srcR does not intersect the surface bounds.
|
2014-12-10 17:53:42 +00:00
|
|
|
* - If the requested colortype/alphatype cannot be converted from the surface's types.
|
2014-12-09 22:39:44 +00:00
|
|
|
*/
|
|
|
|
bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
|
|
|
|
int srcX, int srcY);
|
|
|
|
|
2014-09-22 14:29:03 +00:00
|
|
|
const SkSurfaceProps& props() const { return fProps; }
|
|
|
|
|
Add wrapBackendTextureAsRenderTarget API
Skia's GrTextureProvider currently exposes two APIs for wrapping backend
objects:
* wrapBackendTexture - wraps a texture into a GrTexture. Depending on
flags, this GrTexture can be converted to a GrRenderTarget. Skia
manages the render target objects it may create to provide a render
target for the texture. This allows Skia to create stencil buffers
if needed and manager MSAA resolves.
* wrapBackendRenderTarget - wraps a FBO into a GrRenderTarget. This
object cannot be converted to a GrTexture. Skia does not manage
the render target objects for such a GrRenderTarget, and as such
cannot attach stencil buffers or perform MSAA resolves on the
created GrRenderTarget.
Given these two options, wrapBackendTexture provides more versatility
and allows Skia more room for optimization. Chrome currently uses
wrapBackendTexture for this reason.
While these two functions cover most cases, they do not provide a way
for Skia to wrap a texture into a render target (and gain the MSAA and
stencil buffer management), without also creating a GrTexture. This is
problematic in cases where a texture can be bound to a render target,
but cannot be textured from, as is the case in Chrome's limited support
for GL_TEXTURE_RECTANGLE.
To address this, a new function is created:
* wrapBackendTextureAsRenderTarget - wraps a texture into a
GrRenderTarget. As with wrapBackendTexture, the created render
target objects are fully managed by Skia. Unlike wrapBackendTexture
no GrTexture is created, and the created object will never be
textured from.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1709163003
Review URL: https://codereview.chromium.org/1709163003
2016-02-24 22:49:51 +00:00
|
|
|
/**
|
|
|
|
* Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA.
|
|
|
|
*/
|
|
|
|
void prepareForExternalIO();
|
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
protected:
|
2014-09-22 14:29:03 +00:00
|
|
|
SkSurface(int width, int height, const SkSurfaceProps*);
|
|
|
|
SkSurface(const SkImageInfo&, const SkSurfaceProps*);
|
2012-07-27 21:10:42 +00:00
|
|
|
|
2012-08-28 12:19:02 +00:00
|
|
|
// called by subclass if their contents have changed
|
|
|
|
void dirtyGenerationID() {
|
|
|
|
fGenerationID = 0;
|
|
|
|
}
|
|
|
|
|
2012-07-27 21:10:42 +00:00
|
|
|
private:
|
2014-09-22 14:29:03 +00:00
|
|
|
const SkSurfaceProps fProps;
|
|
|
|
const int fWidth;
|
|
|
|
const int fHeight;
|
|
|
|
uint32_t fGenerationID;
|
2012-08-30 14:38:00 +00:00
|
|
|
|
2012-08-28 12:48:35 +00:00
|
|
|
typedef SkRefCnt INHERITED;
|
2012-07-27 21:10:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|