TestUtils.cpp revision e5da4ef971258193cd1e89737a12b95b6ac244bb
116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck/*
216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Copyright (C) 2015 The Android Open Source Project
316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck *
416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Licensed under the Apache License, Version 2.0 (the "License");
516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * you may not use this file except in compliance with the License.
616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * You may obtain a copy of the License at
716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck *
816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck *      http://www.apache.org/licenses/LICENSE-2.0
916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck *
1016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * Unless required by applicable law or agreed to in writing, software
1116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * distributed under the License is distributed on an "AS IS" BASIS,
1216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * See the License for the specific language governing permissions and
1416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck * limitations under the License.
1516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck */
1616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
1716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include "TestUtils.h"
1816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
19d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "DeferredLayerUpdater.h"
20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "LayerRenderer.h"
21d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
22e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck#include <unistd.h>
23e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck#include <signal.h>
24e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck#include <setjmp.h>
25e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
2616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace android {
2716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recknamespace uirenderer {
2816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
2916c9d6a92e1b86d448c00c52a1630f3e71e6df76John ReckSkColor TestUtils::interpolateColor(float fraction, SkColor start, SkColor end) {
3016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startA = (start >> 24) & 0xff;
3116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startR = (start >> 16) & 0xff;
3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startG = (start >> 8) & 0xff;
3316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int startB = start & 0xff;
3416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
3516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endA = (end >> 24) & 0xff;
3616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endR = (end >> 16) & 0xff;
3716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endG = (end >> 8) & 0xff;
3816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    int endB = end & 0xff;
3916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
4016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    return (int)((startA + (int)(fraction * (endA - startA))) << 24)
4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startR + (int)(fraction * (endR - startR))) << 16)
4216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startG + (int)(fraction * (endG - startG))) << 8)
4316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            | (int)((startB + (int)(fraction * (endB - startB))));
4416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck}
4516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
46d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craiksp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater(
47d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
48d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        std::function<void(Matrix4*)> transformSetupCallback) {
49d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    bool isOpaque = true;
50d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    bool forceFilter = true;
51d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    GLenum renderTarget = GL_TEXTURE_EXTERNAL_OES;
52d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
53d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState());
54d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, forceFilter,
55d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            renderTarget, Matrix4::identity().data);
56d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    transformSetupCallback(&(layer->getTransform()));
57d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
58d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer);
59d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    return layerUpdater;
60d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik}
61d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
62a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
6342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        const SkPaint& paint, float x, float y) {
6442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
6542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
6642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik            "must use glyph encoding");
6742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
68d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
69a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
7042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    float totalAdvance = 0;
7142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    std::vector<glyph_t> glyphs;
7242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    std::vector<float> positions;
7342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    Rect bounds;
7442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    while (*text != '\0') {
7542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkUnichar unichar = SkUTF8_NextUnichar(&text);
7642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        glyph_t glyph = autoCache.getCache()->unicharToGlyph(unichar);
7742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        autoCache.getCache()->unicharToGlyph(unichar);
78a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
7942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // push glyph and its relative position
8042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        glyphs.push_back(glyph);
8142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        positions.push_back(totalAdvance);
8242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        positions.push_back(0);
83a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
8442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // compute bounds
8542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkGlyph skGlyph = autoCache.getCache()->getUnicharMetrics(unichar);
8642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        Rect glyphBounds(skGlyph.fWidth, skGlyph.fHeight);
8742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        glyphBounds.translate(totalAdvance + skGlyph.fLeft, skGlyph.fTop);
8842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        bounds.unionWith(glyphBounds);
89a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
9042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        // advance next character
9142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        SkScalar skWidth;
9242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        paint.getTextWidths(&glyph, sizeof(glyph), &skWidth, NULL);
9342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        totalAdvance += skWidth;
9442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    }
9542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
9642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // apply alignment via x parameter (which JNI layer would have done)
9742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    if (paint.getTextAlign() == SkPaint::kCenter_Align) {
9842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        x -= totalAdvance / 2;
9942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
10042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        x -= totalAdvance;
10142a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    }
10242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
10342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    bounds.translate(x, y);
10442a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik
10542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    // Force left alignment, since alignment offset is already baked in
10642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    SkPaint alignPaintCopy(paint);
10742a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    alignPaintCopy.setTextAlign(SkPaint::kLeft_Align);
10842a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik    canvas->drawText(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y,
10942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik                bounds.left, bounds.top, bounds.right, bounds.bottom, totalAdvance);
110a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
111a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
112d7448e65e243754f31890baef29dff187dc2e5e5Chris Craikvoid TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
113d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        const SkPaint& paint, const SkPath& path) {
114d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
115d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
116d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            "must use glyph encoding");
117d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
118d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    SkAutoGlyphCacheNoGamma autoCache(paint, &surfaceProps, &SkMatrix::I());
119d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
120d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    std::vector<glyph_t> glyphs;
121d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    while (*text != '\0') {
122d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        SkUnichar unichar = SkUTF8_NextUnichar(&text);
123d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        glyphs.push_back(autoCache.getCache()->unicharToGlyph(unichar));
124d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    }
125d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    canvas->drawTextOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
126d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik}
127d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
128e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckstatic void defaultCrashHandler() {
129e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    fprintf(stderr, "RenderThread crashed!");
130e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck}
131e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
132e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckstatic jmp_buf gErrJmpBuff;
133e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckstatic std::function<void()> gCrashHandler = defaultCrashHandler;
134e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
135e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckstatic void signalHandler(int sig) {
136e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    longjmp(gErrJmpBuff, 1);
137e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck}
138e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
139e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckvoid TestUtils::setRenderThreadCrashHandler(std::function<void()> crashHandler) {
140e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    gCrashHandler = crashHandler;
141e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck}
142e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
143e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reckvoid TestUtils::TestTask::run() {
144e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    struct sigaction act;
145e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    memset(&act, 0, sizeof(act));
146e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    act.sa_handler = signalHandler;
147e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
148e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    if (setjmp(gErrJmpBuff)) {
149e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck        gCrashHandler();
150e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck        return;
151e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    }
152e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
153e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    sigaction(SIGABRT, &act, nullptr);
154e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
155e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
156e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    // RenderState only valid once RenderThread is running, so queried here
157e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
158e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
159e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    renderState.onGLContextCreated();
160e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    rtCallback(renderthread::RenderThread::getInstance());
161e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck    renderState.onGLContextDestroyed();
162e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck}
163e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck
16416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace uirenderer */
16516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck} /* namespace android */
166