| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #ifndef SKIA_EXT_CDL_SURFACE_H_ |
| 9 #define SKIA_EXT_CDL_SURFACE_H_ |
| 10 |
| 11 #include "cdl_common.h" |
| 12 |
| 13 #if CDL_ENABLED |
| 14 |
| 15 #include "third_party/skia/include/core/SkImage.h" |
| 16 #include "third_party/skia/include/core/SkRefCnt.h" |
| 17 #include "third_party/skia/include/core/SkSurface.h" |
| 18 #include "third_party/skia/include/core/SkSurfaceProps.h" |
| 19 |
| 20 class GrContext; |
| 21 class GrRenderTarget; |
| 22 |
| 23 class SK_API CdlSurface : public SkRefCnt { |
| 24 public: |
| 25 CdlSurface(sk_sp<SkSurface> surface); |
| 26 ~CdlSurface() override; |
| 27 |
| 28 /** |
| 29 * Create a new surface, using the specified pixels/rowbytes as its |
| 30 * backend. |
| 31 * |
| 32 * If the requested surface cannot be created, or the request is not a |
| 33 * supported configuration, NULL will be returned. |
| 34 * |
| 35 * Callers are responsible for initialiazing the surface pixels. |
| 36 */ |
| 37 static sk_sp<CdlSurface> MakeRasterDirect(const SkImageInfo&, |
| 38 void* pixels, |
| 39 size_t rowBytes, |
| 40 const SkSurfaceProps* = nullptr); |
| 41 |
| 42 /** |
| 43 * The same as NewRasterDirect, but also accepts a call-back routine, which |
| 44 * is invoked |
| 45 * when the surface is deleted, and is passed the pixel memory and the |
| 46 * specified context. |
| 47 */ |
| 48 static sk_sp<CdlSurface> MakeRasterDirectReleaseProc( |
| 49 const SkImageInfo&, |
| 50 void* pixels, |
| 51 size_t rowBytes, |
| 52 void (*releaseProc)(void* pixels, void* context), |
| 53 void* context, |
| 54 const SkSurfaceProps* = nullptr); |
| 55 |
| 56 /** |
| 57 * Return a new surface, with the memory for the pixels automatically |
| 58 * allocated and |
| 59 * zero-initialized, but respecting the specified rowBytes. If rowBytes==0, |
| 60 * then a default |
| 61 * value will be chosen. If a non-zero rowBytes is specified, then any images |
| 62 * snapped off of |
| 63 * this surface (via makeImageSnapshot()) are guaranteed to have the same |
| 64 * rowBytes. |
| 65 * |
| 66 * If the requested surface cannot be created, or the request is not a |
| 67 * supported configuration, NULL will be returned. |
| 68 */ |
| 69 static sk_sp<CdlSurface> MakeRaster(const SkImageInfo&, |
| 70 size_t rowBytes, |
| 71 const SkSurfaceProps*); |
| 72 |
| 73 /** |
| 74 * Allocate a new surface, automatically computing the rowBytes. |
| 75 */ |
| 76 static sk_sp<CdlSurface> MakeRaster(const SkImageInfo& info, |
| 77 const SkSurfaceProps* props = nullptr) { |
| 78 return MakeRaster(info, 0, props); |
| 79 } |
| 80 |
| 81 /** |
| 82 * Helper version of NewRaster. It creates a SkImageInfo with the |
| 83 * specified width and height, and populates the rest of info to match |
| 84 * pixels in SkPMColor format. |
| 85 */ |
| 86 static sk_sp<CdlSurface> MakeRasterN32Premul( |
| 87 int width, |
| 88 int height, |
| 89 const SkSurfaceProps* props = nullptr) { |
| 90 return MakeRaster(SkImageInfo::MakeN32Premul(width, height), props); |
| 91 } |
| 92 |
| 93 /** |
| 94 * Used to wrap a pre-existing backend 3D API texture as a SkSurface. The |
| 95 * kRenderTarget flag |
| 96 * must be set on GrBackendTextureDesc for this to succeed. Skia will not |
| 97 * assume ownership |
| 98 * of the texture and the client must ensure the texture is valid for the |
| 99 * lifetime of the |
| 100 * SkSurface. |
| 101 */ |
| 102 static sk_sp<CdlSurface> MakeFromBackendTexture(GrContext*, |
| 103 const GrBackendTextureDesc&, |
| 104 sk_sp<SkColorSpace>, |
| 105 const SkSurfaceProps*); |
| 106 |
| 107 /** |
| 108 * Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia |
| 109 * will not assume |
| 110 * ownership of the render target and the client must ensure the render |
| 111 * target is valid for the |
| 112 * lifetime of the SkSurface. |
| 113 */ |
| 114 static sk_sp<CdlSurface> MakeFromBackendRenderTarget( |
| 115 GrContext*, |
| 116 const GrBackendRenderTargetDesc&, |
| 117 sk_sp<SkColorSpace>, |
| 118 const SkSurfaceProps*); |
| 119 |
| 120 /** |
| 121 * Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat |
| 122 * the texture as |
| 123 * a rendering target only, but unlike NewFromBackendRenderTarget, Skia will |
| 124 * manage and own |
| 125 * the associated render target objects (but not the provided texture). The |
| 126 * kRenderTarget flag |
| 127 * must be set on GrBackendTextureDesc for this to succeed. Skia will not |
| 128 * assume ownership |
| 129 * of the texture and the client must ensure the texture is valid for the |
| 130 * lifetime of the |
| 131 * SkSurface. |
| 132 */ |
| 133 static sk_sp<CdlSurface> MakeFromBackendTextureAsRenderTarget( |
| 134 GrContext*, |
| 135 const GrBackendTextureDesc&, |
| 136 sk_sp<SkColorSpace>, |
| 137 const SkSurfaceProps*); |
| 138 |
| 139 /** |
| 140 * Legacy versions of the above factories, without color space support. These |
| 141 * create "legacy" |
| 142 * surfaces that operate without gamma correction or color management. |
| 143 */ |
| 144 static sk_sp<CdlSurface> MakeFromBackendTexture( |
| 145 GrContext* ctx, |
| 146 const GrBackendTextureDesc& desc, |
| 147 const SkSurfaceProps* props) { |
| 148 return MakeFromBackendTexture(ctx, desc, nullptr, props); |
| 149 } |
| 150 |
| 151 static sk_sp<CdlSurface> MakeFromBackendRenderTarget( |
| 152 GrContext* ctx, |
| 153 const GrBackendRenderTargetDesc& desc, |
| 154 const SkSurfaceProps* props) { |
| 155 return MakeFromBackendRenderTarget(ctx, desc, nullptr, props); |
| 156 } |
| 157 |
| 158 static sk_sp<CdlSurface> MakeFromBackendTextureAsRenderTarget( |
| 159 GrContext* ctx, |
| 160 const GrBackendTextureDesc& desc, |
| 161 const SkSurfaceProps* props) { |
| 162 return MakeFromBackendTextureAsRenderTarget(ctx, desc, nullptr, props); |
| 163 } |
| 164 |
| 165 /** |
| 166 * Return a new surface whose contents will be drawn to an offscreen |
| 167 * render target, allocated by the surface. |
| 168 */ |
| 169 static sk_sp<CdlSurface> MakeRenderTarget(GrContext*, |
| 170 SkBudgeted, |
| 171 const SkImageInfo&, |
| 172 int sampleCount, |
| 173 GrSurfaceOrigin, |
| 174 const SkSurfaceProps*); |
| 175 |
| 176 static sk_sp<CdlSurface> MakeRenderTarget(GrContext* context, |
| 177 SkBudgeted budgeted, |
| 178 const SkImageInfo& info, |
| 179 int sampleCount, |
| 180 const SkSurfaceProps* props) { |
| 181 return MakeRenderTarget(context, budgeted, info, sampleCount, |
| 182 kBottomLeft_GrSurfaceOrigin, props); |
| 183 } |
| 184 |
| 185 static sk_sp<CdlSurface> MakeRenderTarget(GrContext* gr, |
| 186 SkBudgeted b, |
| 187 const SkImageInfo& info) { |
| 188 if (!info.width() || !info.height()) { |
| 189 return nullptr; |
| 190 } |
| 191 return MakeRenderTarget(gr, b, info, 0, kBottomLeft_GrSurfaceOrigin, |
| 192 nullptr); |
| 193 } |
| 194 |
| 195 int width() const { return surface_->width(); } |
| 196 int height() const { return surface_->height(); } |
| 197 |
| 198 /** |
| 199 * Returns a unique non-zero, unique value identifying the content of this |
| 200 * surface. Each time the content is changed changed, either by drawing |
| 201 * into this surface, or explicitly calling notifyContentChanged()) this |
| 202 * method will return a new value. |
| 203 * |
| 204 * If this surface is empty (i.e. has a zero-dimention), this will return |
| 205 * 0. |
| 206 */ |
| 207 uint32_t generationID() { return surface_->generationID(); } |
| 208 |
| 209 /** |
| 210 * Call this if the contents are about to change. This will (lazily) force a |
| 211 * new |
| 212 * value to be returned from generationID() when it is called next. |
| 213 * |
| 214 * CAN WE DEPRECATE THIS? |
| 215 */ |
| 216 void notifyContentWillChange(SkSurface::ContentChangeMode mode) { |
| 217 surface_->notifyContentWillChange(mode); |
| 218 } |
| 219 |
| 220 enum BackendHandleAccess { |
| 221 kFlushRead_BackendHandleAccess, //!< caller may read from the backend |
| 222 //! object |
| 223 kFlushWrite_BackendHandleAccess, //!< caller may write to the backend |
| 224 //! object |
| 225 kDiscardWrite_BackendHandleAccess, //!< caller must over-write the entire |
| 226 //! backend object |
| 227 }; |
| 228 |
| 229 /* |
| 230 * These are legacy aliases which will be removed soon |
| 231 */ |
| 232 static const BackendHandleAccess kFlushRead_TextureHandleAccess = |
| 233 kFlushRead_BackendHandleAccess; |
| 234 static const BackendHandleAccess kFlushWrite_TextureHandleAccess = |
| 235 kFlushWrite_BackendHandleAccess; |
| 236 static const BackendHandleAccess kDiscardWrite_TextureHandleAccess = |
| 237 kDiscardWrite_BackendHandleAccess; |
| 238 |
| 239 /** |
| 240 * Retrieves the backend API handle of the texture used by this surface, or 0 |
| 241 * if the surface |
| 242 * is not backed by a GPU texture. |
| 243 * |
| 244 * The returned texture-handle is only valid until the next draw-call into |
| 245 * the surface, |
| 246 * or the surface is deleted. |
| 247 */ |
| 248 GrBackendObject getTextureHandle(BackendHandleAccess); |
| 249 |
| 250 /** |
| 251 * Retrieves the backend API handle of the RenderTarget backing this surface. |
| 252 * Callers must |
| 253 * ensure this function returns 'true' or else the GrBackendObject will be |
| 254 * invalid |
| 255 * |
| 256 * In OpenGL this will return the FramebufferObject ID. |
| 257 */ |
| 258 bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess); |
| 259 |
| 260 /** |
| 261 * Return a canvas that will draw into this surface. This will always |
| 262 * return the same canvas for a given surface, and is manged/owned by the |
| 263 * surface. It should not be used when its parent surface has gone out of |
| 264 * scope. |
| 265 */ |
| 266 CdlCanvas* getCanvas(); |
| 267 |
| 268 /** |
| 269 * Return a new surface that is "compatible" with this one, in that it will |
| 270 * efficiently be able to be drawn into this surface. Typical calling |
| 271 * pattern: |
| 272 * |
| 273 * SkSurface* A = SkSurface::New...(); |
| 274 * SkCanvas* canvasA = surfaceA->newCanvas(); |
| 275 * ... |
| 276 * SkSurface* surfaceB = surfaceA->newSurface(...); |
| 277 * SkCanvas* canvasB = surfaceB->newCanvas(); |
| 278 * ... // draw using canvasB |
| 279 * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! |
| 280 */ |
| 281 sk_sp<SkSurface> makeSurface(const SkImageInfo&); |
| 282 |
| 283 /** |
| 284 * Returns an image of the current state of the surface pixels up to this |
| 285 * point. Subsequent changes to the surface (by drawing into its canvas) |
| 286 * will not be reflected in this image. If a copy must be made the Budgeted |
| 287 * parameter controls whether it counts against the resource budget |
| 288 * (currently for the gpu backend only). |
| 289 */ |
| 290 sk_sp<SkImage> makeImageSnapshot(SkBudgeted = SkBudgeted::kYes); |
| 291 |
| 292 /** |
| 293 * In rare instances a client may want a unique copy of the SkSurface's |
| 294 * contents in an image |
| 295 * snapshot. This enum can be used to enforce that the image snapshot's |
| 296 * backing store is not |
| 297 * shared with another image snapshot or the surface's backing store. This is |
| 298 * generally more |
| 299 * expensive. This was added for Chromium bug 585250. |
| 300 */ |
| 301 enum ForceUnique { kNo_ForceUnique, kYes_ForceUnique }; |
| 302 sk_sp<SkImage> makeImageSnapshot(SkBudgeted, ForceUnique); |
| 303 |
| 304 /** |
| 305 * Though the caller could get a snapshot image explicitly, and draw that, |
| 306 * it seems that directly drawing a surface into another canvas might be |
| 307 * a common pattern, and that we could possibly be more efficient, since |
| 308 * we'd know that the "snapshot" need only live until we've handed it off |
| 309 * to the canvas. |
| 310 */ |
| 311 void draw(CdlCanvas*, SkScalar x, SkScalar y, const CdlPaint*); |
| 312 |
| 313 /** |
| 314 * If the surface has direct access to its pixels (i.e. they are in local |
| 315 * RAM) return true, and if not null, set the pixmap parameter to point to |
| 316 * the information |
| 317 * about the surface's pixels. The pixel address in the pixmap is only valid |
| 318 * while |
| 319 * the surface object is in scope, and no API call is made on the surface |
| 320 * or its canvas. |
| 321 * |
| 322 * On failure, returns false and the pixmap parameter is ignored. |
| 323 */ |
| 324 bool peekPixels(SkPixmap*); |
| 325 |
| 326 /** |
| 327 * Copy the pixels from the surface into the specified buffer (pixels + |
| 328 * rowBytes), |
| 329 * converting them into the requested format (dstInfo). The surface pixels |
| 330 * are read |
| 331 * starting at the specified (srcX,srcY) location. |
| 332 * |
| 333 * The specified ImageInfo and (srcX,srcY) offset specifies a source |
| 334 * rectangle |
| 335 * |
| 336 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height()); |
| 337 * |
| 338 * srcR is intersected with the bounds of the base-layer. If this |
| 339 * intersection is not empty, |
| 340 * then we have two sets of pixels (of equal size). Replace the dst pixels |
| 341 * with the |
| 342 * corresponding src pixels, performing any colortype/alphatype |
| 343 * transformations needed |
| 344 * (in the case where the src and dst have different colortypes or |
| 345 * alphatypes). |
| 346 * |
| 347 * This call can fail, returning false, for several reasons: |
| 348 * - If srcR does not intersect the surface bounds. |
| 349 * - If the requested colortype/alphatype cannot be converted from the |
| 350 * surface's types. |
| 351 */ |
| 352 bool readPixels(const SkImageInfo& dstInfo, |
| 353 void* dstPixels, |
| 354 size_t dstRowBytes, |
| 355 int srcX, |
| 356 int srcY); |
| 357 |
| 358 const SkSurfaceProps& props() const { return surface_->props(); } |
| 359 |
| 360 /** |
| 361 * Issue any pending surface IO to the current backend 3D API and resolve any |
| 362 * surface MSAA. |
| 363 */ |
| 364 void prepareForExternalIO(); |
| 365 |
| 366 private: |
| 367 sk_sp<SkSurface> surface_; |
| 368 std::unique_ptr<CdlCanvas> canvas_; |
| 369 }; |
| 370 |
| 371 #endif // CDL_ENABLED |
| 372 |
| 373 #endif // SKIA_EXT_CDL_SURFACE_H_ |
| OLD | NEW |