TestUtils.cpp revision 5e4389823191aafff7422561f134dbdb391e0a2d
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "TestUtils.h" 18 19#include "hwui/Paint.h" 20#include "DeferredLayerUpdater.h" 21 22#include <renderthread/EglManager.h> 23#include <renderthread/OpenGLPipeline.h> 24#include <pipeline/skia/SkiaOpenGLPipeline.h> 25#include <pipeline/skia/SkiaVulkanPipeline.h> 26#include <renderthread/VulkanManager.h> 27#include <utils/Unicode.h> 28#include <SkClipStack.h> 29 30#include <SkGlyphCache.h> 31 32namespace android { 33namespace uirenderer { 34 35SkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) { 36 int startA = (start >> 24) & 0xff; 37 int startR = (start >> 16) & 0xff; 38 int startG = (start >> 8) & 0xff; 39 int startB = start & 0xff; 40 41 int endA = (end >> 24) & 0xff; 42 int endR = (end >> 16) & 0xff; 43 int endG = (end >> 8) & 0xff; 44 int endB = end & 0xff; 45 46 return (int)((startA + (int)(fraction * (endA - startA))) << 24) 47 | (int)((startR + (int)(fraction * (endR - startR))) << 16) 48 | (int)((startG + (int)(fraction * (endG - startG))) << 8) 49 | (int)((startB + (int)(fraction * (endB - startB)))); 50} 51 52sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( 53 renderthread::RenderThread& renderThread) { 54 android::uirenderer::renderthread::IRenderPipeline* pipeline; 55 if (Properties::getRenderPipelineType() == RenderPipelineType::OpenGL) { 56 pipeline = new renderthread::OpenGLPipeline(renderThread); 57 } else if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { 58 pipeline = new skiapipeline::SkiaOpenGLPipeline(renderThread); 59 } else { 60 pipeline = new skiapipeline::SkiaVulkanPipeline(renderThread); 61 } 62 sp<DeferredLayerUpdater> layerUpdater = pipeline->createTextureLayer(); 63 delete pipeline; 64 return layerUpdater; 65} 66 67sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( 68 renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, 69 const SkMatrix& transform) { 70 sp<DeferredLayerUpdater> layerUpdater = createTextureLayerUpdater(renderThread); 71 layerUpdater->backingLayer()->getTransform().load(transform); 72 layerUpdater->setSize(width, height); 73 layerUpdater->setTransform(&transform); 74 75 // updateLayer so it's ready to draw 76 layerUpdater->updateLayer(true, GL_TEXTURE_EXTERNAL_OES, Matrix4::identity().data); 77 return layerUpdater; 78} 79 80void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text, 81 std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions, 82 float* outTotalAdvance, Rect* outBounds) { 83 Rect bounds; 84 float totalAdvance = 0; 85 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); 86 SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I()); 87 while (*text != '\0') { 88 size_t nextIndex = 0; 89 int32_t unichar = utf32_from_utf8_at(text, 4, 0, &nextIndex); 90 text += nextIndex; 91 92 glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar); 93 autoCache.getCache()->unicharToGlyph(unichar); 94 95 // push glyph and its relative position 96 outGlyphs->push_back(glyph); 97 outPositions->push_back(totalAdvance); 98 outPositions->push_back(0); 99 100 // compute bounds 101 SkGlyph skGlyph = autoCache.getCache()->getUnicharMetrics(unichar); 102 Rect glyphBounds(skGlyph.fWidth, skGlyph.fHeight); 103 glyphBounds.translate(totalAdvance + skGlyph.fLeft, skGlyph.fTop); 104 bounds.unionWith(glyphBounds); 105 106 // advance next character 107 SkScalar skWidth; 108 paint.getTextWidths(&glyph, sizeof(glyph), &skWidth, NULL); 109 totalAdvance += skWidth; 110 } 111 *outBounds = bounds; 112 *outTotalAdvance = totalAdvance; 113} 114 115 116void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 117 const SkPaint& paint, float x, float y) { 118 auto utf16 = asciiToUtf16(text); 119 canvas->drawText(utf16.get(), 0, strlen(text), strlen(text), x, y, 0, paint, nullptr); 120} 121 122void TestUtils::drawUtf8ToCanvas(Canvas* canvas, const char* text, 123 const SkPaint& paint, const SkPath& path) { 124 auto utf16 = asciiToUtf16(text); 125 canvas->drawTextOnPath(utf16.get(), strlen(text), 0, path, 0, 0, paint, nullptr); 126} 127 128void TestUtils::TestTask::run() { 129 // RenderState only valid once RenderThread is running, so queried here 130 renderthread::RenderThread& renderThread = renderthread::RenderThread::getInstance(); 131 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { 132 renderThread.vulkanManager().initialize(); 133 } else { 134 renderThread.eglManager().initialize(); 135 } 136 137 rtCallback(renderThread); 138 139 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { 140 renderThread.vulkanManager().destroy(); 141 } else { 142 renderThread.renderState().flush(Caches::FlushMode::Full); 143 renderThread.eglManager().destroy(); 144 } 145} 146 147std::unique_ptr<uint16_t[]> TestUtils::asciiToUtf16(const char* str) { 148 const int length = strlen(str); 149 std::unique_ptr<uint16_t[]> utf16(new uint16_t[length]); 150 for (int i = 0; i < length; i++) { 151 utf16.get()[i] = str[i]; 152 } 153 return utf16; 154} 155 156SkColor TestUtils::getColor(const sk_sp<SkSurface>& surface, int x, int y) { 157 SkPixmap pixmap; 158 if (!surface->peekPixels(&pixmap)) { 159 return 0; 160 } 161 switch (pixmap.colorType()) { 162 case kGray_8_SkColorType: { 163 const uint8_t* addr = pixmap.addr8(x, y); 164 return SkColorSetRGB(*addr, *addr, *addr); 165 } 166 case kAlpha_8_SkColorType: { 167 const uint8_t* addr = pixmap.addr8(x, y); 168 return SkColorSetA(0, addr[0]); 169 } 170 case kRGB_565_SkColorType: { 171 const uint16_t* addr = pixmap.addr16(x, y); 172 return SkPixel16ToColor(addr[0]); 173 } 174 case kARGB_4444_SkColorType: { 175 const uint16_t* addr = pixmap.addr16(x, y); 176 SkPMColor c = SkPixel4444ToPixel32(addr[0]); 177 return SkUnPreMultiply::PMColorToColor(c); 178 } 179 case kBGRA_8888_SkColorType: { 180 const uint32_t* addr = pixmap.addr32(x, y); 181 SkPMColor c = SkSwizzle_BGRA_to_PMColor(addr[0]); 182 return SkUnPreMultiply::PMColorToColor(c); 183 } 184 case kRGBA_8888_SkColorType: { 185 const uint32_t* addr = pixmap.addr32(x, y); 186 SkPMColor c = SkSwizzle_RGBA_to_PMColor(addr[0]); 187 return SkUnPreMultiply::PMColorToColor(c); 188 } 189 default: 190 return 0; 191 } 192 return 0; 193} 194 195SkRect TestUtils::getClipBounds(const SkCanvas* canvas) { 196 return SkRect::Make(canvas->getDeviceClipBounds()); 197} 198 199SkRect TestUtils::getLocalClipBounds(const SkCanvas* canvas) { 200 SkMatrix invertedTotalMatrix; 201 if (!canvas->getTotalMatrix().invert(&invertedTotalMatrix)) { 202 return SkRect::MakeEmpty(); 203 } 204 SkRect outlineInDeviceCoord = TestUtils::getClipBounds(canvas); 205 SkRect outlineInLocalCoord; 206 invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord); 207 return outlineInLocalCoord; 208} 209 210} /* namespace uirenderer */ 211} /* namespace android */ 212