Add SkSurface factory for wrapping an FBO in SkSurface
Review URL: https://codereview.chromium.org/1221853003
This commit is contained in:
parent
c49e8682ab
commit
d3e259a16c
@ -88,11 +88,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to wrap a pre-existing backend 3D API texture in a SkSurface. The kRenderTarget flag
|
* 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.
|
* 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* NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc,
|
static SkSurface* NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
|
||||||
const SkSurfaceProps*);
|
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*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new surface whose contents will be drawn to an offscreen
|
* Return a new surface whose contents will be drawn to an offscreen
|
||||||
|
@ -192,9 +192,14 @@ SkSurface* SkSurface::NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkSurface* SkSurface::NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc,
|
SkSurface* SkSurface::NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
|
||||||
const SkSurfaceProps*) {
|
const SkSurfaceProps*) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&,
|
||||||
|
const SkSurfaceProps*) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -116,8 +116,8 @@ SkSurface* SkSurface::NewRenderTarget(GrContext* ctx, Budgeted budgeted, const S
|
|||||||
return SkNEW_ARGS(SkSurface_Gpu, (device));
|
return SkNEW_ARGS(SkSurface_Gpu, (device));
|
||||||
}
|
}
|
||||||
|
|
||||||
SkSurface* SkSurface::NewWrappedRenderTarget(GrContext* context, GrBackendTextureDesc desc,
|
SkSurface* SkSurface::NewFromBackendTexture(GrContext* context, const GrBackendTextureDesc& desc,
|
||||||
const SkSurfaceProps* props) {
|
const SkSurfaceProps* props) {
|
||||||
if (NULL == context) {
|
if (NULL == context) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -137,4 +137,22 @@ SkSurface* SkSurface::NewWrappedRenderTarget(GrContext* context, GrBackendTextur
|
|||||||
return SkNEW_ARGS(SkSurface_Gpu, (device));
|
return SkNEW_ARGS(SkSurface_Gpu, (device));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkSurface* SkSurface::NewFromBackendRenderTarget(GrContext* context,
|
||||||
|
const GrBackendRenderTargetDesc& desc,
|
||||||
|
const SkSurfaceProps* props) {
|
||||||
|
if (NULL == context) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SkAutoTUnref<GrRenderTarget> rt(context->textureProvider()->wrapBackendRenderTarget(desc));
|
||||||
|
if (!rt) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(rt, props,
|
||||||
|
SkGpuDevice::kUninit_InitContents));
|
||||||
|
if (!device) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return SkNEW_ARGS(SkSurface_Gpu, (device));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -102,7 +102,7 @@ static void test_empty_surface(skiatest::Reporter* reporter, GrContext* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext* ctx) {
|
static void test_wrapped_surface(skiatest::Reporter* reporter, GrContext* ctx) {
|
||||||
if (NULL == ctx) {
|
if (NULL == ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -120,77 +120,107 @@ static void test_wrapped_texture_surface(skiatest::Reporter* reporter, GrContext
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the wrapped factory for SkSurface by creating a texture using GL and then wrap it in
|
for (int useFBO = 0; useFBO < 2; ++useFBO) {
|
||||||
// a SkSurface.
|
// Test the wrapped factory for SkSurface by creating a texture using GL and then wrap it in
|
||||||
GrGLuint texID;
|
// a SkSurface.
|
||||||
static const int kW = 100;
|
GrGLuint texID;
|
||||||
static const int kH = 100;
|
static const int kW = 100;
|
||||||
static const uint32_t kOrigColor = 0xFFAABBCC;
|
static const int kH = 100;
|
||||||
SkAutoTArray<uint32_t> pixels(kW * kH);
|
static const uint32_t kOrigColor = 0xFFAABBCC;
|
||||||
sk_memset32(pixels.get(), kOrigColor, kW * kH);
|
SkAutoTArray<uint32_t> pixels(kW * kH);
|
||||||
GR_GL_CALL(gl, GenTextures(1, &texID));
|
sk_memset32(pixels.get(), kOrigColor, kW * kH);
|
||||||
GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0));
|
GR_GL_CALL(gl, GenTextures(1, &texID));
|
||||||
GR_GL_CALL(gl, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
|
GR_GL_CALL(gl, ActiveTexture(GR_GL_TEXTURE0));
|
||||||
GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texID));
|
GR_GL_CALL(gl, PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
|
||||||
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER,
|
GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, texID));
|
||||||
GR_GL_NEAREST));
|
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER,
|
||||||
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER,
|
GR_GL_NEAREST));
|
||||||
GR_GL_NEAREST));
|
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MIN_FILTER,
|
||||||
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S,
|
GR_GL_NEAREST));
|
||||||
GR_GL_CLAMP_TO_EDGE));
|
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S,
|
||||||
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T,
|
GR_GL_CLAMP_TO_EDGE));
|
||||||
GR_GL_CLAMP_TO_EDGE));
|
GR_GL_CALL(gl, TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T,
|
||||||
GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, kW, kH, 0, GR_GL_RGBA,
|
GR_GL_CLAMP_TO_EDGE));
|
||||||
GR_GL_UNSIGNED_BYTE,
|
GR_GL_CALL(gl, TexImage2D(GR_GL_TEXTURE_2D, 0, GR_GL_RGBA, kW, kH, 0, GR_GL_RGBA,
|
||||||
pixels.get()));
|
GR_GL_UNSIGNED_BYTE,
|
||||||
|
pixels.get()));
|
||||||
|
|
||||||
GrBackendTextureDesc wrappedDesc;
|
SkAutoTUnref<SkSurface> surface;
|
||||||
wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
GrGLuint fboID = 0;
|
||||||
wrappedDesc.fWidth = kW;
|
if (useFBO) {
|
||||||
wrappedDesc.fHeight = kH;
|
GR_GL_CALL(gl, GenFramebuffers(1, &fboID));
|
||||||
wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
|
GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, fboID));
|
||||||
wrappedDesc.fSampleCnt = 0;
|
GR_GL_CALL(gl, FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
|
||||||
wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
|
GR_GL_TEXTURE_2D, texID, 0));
|
||||||
wrappedDesc.fTextureHandle = texID;
|
GrBackendRenderTargetDesc wrappedDesc;
|
||||||
|
wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||||
|
wrappedDesc.fWidth = kW;
|
||||||
|
wrappedDesc.fHeight = kH;
|
||||||
|
wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
|
||||||
|
wrappedDesc.fSampleCnt = 0;
|
||||||
|
wrappedDesc.fRenderTargetHandle = fboID;
|
||||||
|
wrappedDesc.fStencilBits = 0;
|
||||||
|
|
||||||
SkAutoTUnref<SkSurface> surface(SkSurface::NewWrappedRenderTarget(ctx, wrappedDesc, NULL));
|
ctx->resetContext();
|
||||||
REPORTER_ASSERT(reporter, surface);
|
surface.reset(SkSurface::NewFromBackendRenderTarget(ctx, wrappedDesc, NULL));
|
||||||
if (surface) {
|
} else {
|
||||||
// Validate that we can draw to the canvas and that the original texture color is preserved
|
GrBackendTextureDesc wrappedDesc;
|
||||||
// in pixels that aren't rendered to via the surface.
|
wrappedDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||||
SkPaint paint;
|
wrappedDesc.fWidth = kW;
|
||||||
static const SkColor kRectColor = ~kOrigColor | 0xFF000000;
|
wrappedDesc.fHeight = kH;
|
||||||
paint.setColor(kRectColor);
|
wrappedDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
|
||||||
surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
|
wrappedDesc.fSampleCnt = 0;
|
||||||
paint);
|
wrappedDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
|
||||||
SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH);
|
wrappedDesc.fTextureHandle = texID;
|
||||||
surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0);
|
|
||||||
bool stop = false;
|
ctx->resetContext();
|
||||||
SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF),
|
surface.reset(SkSurface::NewFromBackendTexture(ctx, wrappedDesc, NULL));
|
||||||
(kOrigColor >> 0 & 0xFF),
|
}
|
||||||
(kOrigColor >> 8 & 0xFF),
|
REPORTER_ASSERT(reporter, surface);
|
||||||
(kOrigColor >> 16 & 0xFF));
|
if (surface) {
|
||||||
SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF),
|
// Validate that we can draw to the canvas and that the original texture color is
|
||||||
(kRectColor >> 16 & 0xFF),
|
// preserved in pixels that aren't rendered to via the surface.
|
||||||
(kRectColor >> 8 & 0xFF),
|
SkPaint paint;
|
||||||
(kRectColor >> 0 & 0xFF));
|
static const SkColor kRectColor = ~kOrigColor | 0xFF000000;
|
||||||
for (int y = 0; y < kH/2 && !stop; ++y) {
|
paint.setColor(kRectColor);
|
||||||
for (int x = 0; x < kW && !stop; ++x) {
|
surface->getCanvas()->drawRect(SkRect::MakeWH(SkIntToScalar(kW), SkIntToScalar(kH)/2),
|
||||||
REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
|
paint);
|
||||||
if (rectColorPM != pixels[x + y * kW]) {
|
SkImageInfo readInfo = SkImageInfo::MakeN32Premul(kW, kH);
|
||||||
stop = true;
|
surface->readPixels(readInfo, pixels.get(), kW * sizeof(uint32_t), 0, 0);
|
||||||
|
bool stop = false;
|
||||||
|
SkPMColor origColorPM = SkPackARGB32((kOrigColor >> 24 & 0xFF),
|
||||||
|
(kOrigColor >> 0 & 0xFF),
|
||||||
|
(kOrigColor >> 8 & 0xFF),
|
||||||
|
(kOrigColor >> 16 & 0xFF));
|
||||||
|
SkPMColor rectColorPM = SkPackARGB32((kRectColor >> 24 & 0xFF),
|
||||||
|
(kRectColor >> 16 & 0xFF),
|
||||||
|
(kRectColor >> 8 & 0xFF),
|
||||||
|
(kRectColor >> 0 & 0xFF));
|
||||||
|
for (int y = 0; y < kH/2 && !stop; ++y) {
|
||||||
|
for (int x = 0; x < kW && !stop; ++x) {
|
||||||
|
REPORTER_ASSERT(reporter, rectColorPM == pixels[x + y * kW]);
|
||||||
|
if (rectColorPM != pixels[x + y * kW]) {
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stop = false;
|
||||||
|
for (int y = kH/2; y < kH && !stop; ++y) {
|
||||||
|
for (int x = 0; x < kW && !stop; ++x) {
|
||||||
|
REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
|
||||||
|
if (origColorPM != pixels[x + y * kW]) {
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop = false;
|
if (texID) {
|
||||||
for (int y = kH/2; y < kH && !stop; ++y) {
|
GR_GL_CALL(gl, DeleteTextures(1, &texID));
|
||||||
for (int x = 0; x < kW && !stop; ++x) {
|
|
||||||
REPORTER_ASSERT(reporter, origColorPM == pixels[x + y * kW]);
|
|
||||||
if (origColorPM != pixels[x + y * kW]) {
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (fboID) {
|
||||||
|
GR_GL_CALL(gl, DeleteFramebuffers(1, &fboID));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -837,7 +867,7 @@ DEF_GPUTEST(Surface, reporter, factory) {
|
|||||||
TestGetTexture(reporter, kGpuScratch_SurfaceType, context);
|
TestGetTexture(reporter, kGpuScratch_SurfaceType, context);
|
||||||
test_empty_surface(reporter, context);
|
test_empty_surface(reporter, context);
|
||||||
test_surface_budget(reporter, context);
|
test_surface_budget(reporter, context);
|
||||||
test_wrapped_texture_surface(reporter, context);
|
test_wrapped_surface(reporter, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user