OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2015 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 #include "GrTextureParamsAdjuster.h" | |
9 | |
10 #include "GrCaps.h" | |
11 #include "GrContext.h" | |
12 #include "GrDrawContext.h" | |
13 #include "GrGpu.h" | |
14 #include "GrTexture.h" | |
15 #include "GrTextureParams.h" | |
16 #include "GrTextureProvider.h" | |
17 #include "SkCanvas.h" | |
18 #include "SkGr.h" | |
19 #include "SkGrPriv.h" | |
20 | |
21 typedef GrTextureParamsAdjuster::CopyParams CopyParams; | |
22 | |
23 static GrTexture* copy_on_gpu(GrTexture* inputTexture, const CopyParams& copyPar
ams) { | |
24 GrContext* context = inputTexture->getContext(); | |
25 SkASSERT(context); | |
26 const GrCaps* caps = context->caps(); | |
27 | |
28 // Either it's a cache miss or the original wasn't cached to begin with. | |
29 GrSurfaceDesc rtDesc = inputTexture->desc(); | |
30 rtDesc.fFlags = rtDesc.fFlags | kRenderTarget_GrSurfaceFlag; | |
31 rtDesc.fWidth = copyParams.fWidth; | |
32 rtDesc.fHeight = copyParams.fHeight; | |
33 rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig); | |
34 | |
35 // If the config isn't renderable try converting to either A8 or an 32 bit c
onfig. Otherwise, | |
36 // fail. | |
37 if (!caps->isConfigRenderable(rtDesc.fConfig, false)) { | |
38 if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) { | |
39 if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { | |
40 rtDesc.fConfig = kAlpha_8_GrPixelConfig; | |
41 } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false))
{ | |
42 rtDesc.fConfig = kSkia8888_GrPixelConfig; | |
43 } else { | |
44 return nullptr; | |
45 } | |
46 } else if (kRGB_GrColorComponentFlags == | |
47 (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDe
sc.fConfig))) { | |
48 if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) { | |
49 rtDesc.fConfig = kSkia8888_GrPixelConfig; | |
50 } else { | |
51 return nullptr; | |
52 } | |
53 } else { | |
54 return nullptr; | |
55 } | |
56 } | |
57 | |
58 SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(rtDes
c, true)); | |
59 if (!copy) { | |
60 return nullptr; | |
61 } | |
62 | |
63 GrPaint paint; | |
64 | |
65 // If filtering is not desired then we want to ensure all texels in the resa
mpled image are | |
66 // copies of texels from the original. | |
67 GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter); | |
68 paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params); | |
69 | |
70 SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtD
esc.fHeight)); | |
71 SkRect localRect = SkRect::MakeWH(1.f, 1.f); | |
72 | |
73 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(copy->asRenderT
arget())); | |
74 if (!drawContext) { | |
75 return nullptr; | |
76 } | |
77 | |
78 drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), r
ect, localRect); | |
79 return copy.detach(); | |
80 } | |
81 | |
82 static SkBitmap copy_on_cpu(const SkBitmap& bmp, const CopyParams& copyParams) { | |
83 SkBitmap stretched; | |
84 stretched.allocN32Pixels(copyParams.fWidth, copyParams.fHeight); | |
85 SkCanvas canvas(stretched); | |
86 SkPaint paint; | |
87 switch (copyParams.fFilter) { | |
88 case GrTextureParams::kNone_FilterMode: | |
89 paint.setFilterQuality(kNone_SkFilterQuality); | |
90 break; | |
91 case GrTextureParams::kBilerp_FilterMode: | |
92 paint.setFilterQuality(kLow_SkFilterQuality); | |
93 break; | |
94 case GrTextureParams::kMipMap_FilterMode: | |
95 paint.setFilterQuality(kMedium_SkFilterQuality); | |
96 break; | |
97 } | |
98 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(copyParams.fWidth), | |
99 SkIntToScalar(copyParams.fHeight)); | |
100 canvas.drawBitmapRect(bmp, dstRect, &paint); | |
101 return stretched; | |
102 } | |
103 | |
104 GrTexture* GrTextureParamsAdjuster::refTextureForParams(GrContext* ctx, | |
105 const GrTextureParams& p
arams) { | |
106 CopyParams copyParams; | |
107 if (!ctx->getGpu()->makeCopyForTextureParams(this->width(), this->height(),
params, | |
108 ©Params)) { | |
109 return this->refOriginalTexture(ctx); | |
110 } | |
111 GrUniqueKey copyKey; | |
112 this->makeCopyKey(copyParams, ©Key); | |
113 if (copyKey.isValid()) { | |
114 GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey
(copyKey); | |
115 if (result) { | |
116 return result; | |
117 } | |
118 } | |
119 | |
120 GrTexture* result = this->generateTextureForParams(ctx, copyParams); | |
121 if (!result) { | |
122 return nullptr; | |
123 } | |
124 | |
125 if (copyKey.isValid()) { | |
126 ctx->textureProvider()->assignUniqueKeyToTexture(copyKey, result); | |
127 this->didCacheCopy(copyKey); | |
128 } | |
129 return result; | |
130 } | |
131 | |
132 GrTexture* GrTextureParamsAdjuster::generateTextureForParams(GrContext* ctx, | |
133 const CopyParams& c
opyParams) { | |
134 if (this->width() < ctx->caps()->minTextureSize() || | |
135 this->height() < ctx->caps()->minTextureSize()) | |
136 { | |
137 // we can't trust our ability to use HW to perform the stretch, so we re
quest | |
138 // a raster instead, and perform the stretch on the CPU. | |
139 SkBitmap bitmap; | |
140 if (!this->getROBitmap(&bitmap)) { | |
141 return nullptr; | |
142 } | |
143 SkBitmap stretchedBmp = copy_on_cpu(bitmap, copyParams); | |
144 return GrUploadBitmapToTexture(ctx, stretchedBmp); | |
145 } else { | |
146 SkAutoTUnref<GrTexture> original(this->refOriginalTexture(ctx)); | |
147 if (!original) { | |
148 return nullptr; | |
149 } | |
150 return copy_on_gpu(original, copyParams); | |
151 } | |
152 } | |
OLD | NEW |