Esempio n. 1
0
DEF_TEST(GrGLSLPrettyPrint, r) {
    SkTArray<const char*> testStr;
    SkTArray<int> lengths;
    testStr.push_back(input1.c_str());
    lengths.push_back((int)input1.size());
    testStr.push_back(input2.c_str());
    lengths.push_back((int)input2.size());
    testStr.push_back(input3.c_str());
    lengths.push_back((int)input3.size());
    testStr.push_back(input4.c_str());
    lengths.push_back((int)input4.size());
    testStr.push_back(input5.c_str());
    lengths.push_back((int)input5.size());
    testStr.push_back(input6.c_str());
    lengths.push_back((int)input6.size());

    SkString test = GrGLSLPrettyPrint::PrettyPrintGLSL(testStr.begin(), lengths.begin(),
                                                       testStr.count(), true);
    ASSERT(output1 == test);

    testStr.reset();
    lengths.reset();
    testStr.push_back(neg1.c_str());
    lengths.push_back((int)neg1.size());
    testStr.push_back(neg2.c_str());
    lengths.push_back((int)neg2.size());
    testStr.push_back(neg3.c_str());
    lengths.push_back((int)neg3.size());

    // Just test we don't crash with garbage input
    ASSERT(GrGLSLPrettyPrint::PrettyPrintGLSL(testStr.begin(), lengths.begin(), 1,
                                              true).c_str() != NULL);
}
Esempio n. 2
0
static void handle_cmd(struct android_app* app, int32_t cmd) {
    struct VisualBenchState* state = (struct VisualBenchState*)app->userData;
    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (state->fApp->window != nullptr && kInit_State == state->fState) {
                // drain any events that occurred before |window| was assigned.
                while (SkEvent::ProcessEvent());

                // Start normal Skia sequence
                application_init();

                SkTArray<const char*> args;
                args.push_back("VisualBench");
                for (int i = 0; i < state->fFlags.count(); i++) {
                    SkDebugf(state->fFlags[i].c_str());
                    args.push_back(state->fFlags[i].c_str());
                }

                state->fWindow = create_sk_window((void*)state->fApp->window,
                                                  args.count(),
                                                  const_cast<char**>(args.begin()));
                state->fWindow->forceInvalAll();
                state->fState = kAnimate_State;
            }
            break;
        case APP_CMD_TERM_WINDOW:
            state->fState = kDestroyRequested_State;
            break;
    }
}
Esempio n. 3
0
void GLCpuPosInstancedArraysBench::teardown(const GrGLInterface* gl) {
    GR_GL_CALL(gl, BindBuffer(GR_GL_ARRAY_BUFFER, 0));
    GR_GL_CALL(gl, BindVertexArray(0));
    GR_GL_CALL(gl, BindTexture(GR_GL_TEXTURE_2D, 0));
    GR_GL_CALL(gl, BindFramebuffer(GR_GL_FRAMEBUFFER, 0));
    GR_GL_CALL(gl, DeleteTextures(1, &fTexture));
    GR_GL_CALL(gl, DeleteProgram(fProgram));
    GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
    GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO));
    fBuffers.reset();
}
Esempio n. 4
0
void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list,
                     bool evenOdd, bool oppEvenOdd) {
    int count = contours.count();
    if (count == 0) {
        return;
    }
    for (int index = 0; index < count; ++index) {
        SkOpContour& contour = contours[index];
        contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd);
        list.push_back(&contour);
    }
    SkTQSort<SkOpContour>(list.begin(), list.end() - 1);
}
JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env,
        jobject thiz, jobject jsampleActivity, jint msaaSampleCount)
{
    // setup jni hooks to the java activity
    gActivityGlue.m_env = env;
    jclass clazz = env->FindClass("com/skia/SkiaSampleActivity");
    gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity);
    gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V");
    gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V");
    gActivityGlue.m_addToDownloads = GetJMethod(env, clazz, "addToDownloads",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    env->DeleteLocalRef(clazz);

    // setup jni hooks to the java renderer
    clazz = env->FindClass("com/skia/SkiaSampleRenderer");
    gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz);
    gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V");
    gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V");
    gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V");
    gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I");
    env->DeleteLocalRef(clazz);

    application_init();
    SkTArray<const char*> args;

    args.push_back("SampleApp");
    // TODO: push ability to select skp dir into the UI
    args.push_back("--pictureDir");
    args.push_back("/sdcard/skiabot/skia_skp");

    SkString msaaSampleCountString;
    if (msaaSampleCount > 0) {
        args.push_back("--msaa");
        msaaSampleCountString.appendS32(static_cast<uint32_t>(msaaSampleCount));
        args.push_back(msaaSampleCountString.c_str());
    }

    gWindow = new SampleWindow(NULL, args.count(), const_cast<char**>(args.begin()), NULL);

    // send the list of slides up to the activity
    const int slideCount = gWindow->sampleCount();
    jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF(""));
    for (int i = 0; i < slideCount; i++) {
        jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str());
        env->SetObjectArrayElement(slideList, i, slideTitle);
        env->DeleteLocalRef(slideTitle);
    }
    env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList);
    env->DeleteLocalRef(slideList);
}
Esempio n. 6
0
    /*
        check start and end of each contour
        if not the same, record them
        match them up
        connect closest
        reassemble contour pieces into new path
    */
void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
#if DEBUG_PATH_CONSTRUCTION
    SkDebugf("%s\n", __FUNCTION__);
#endif
    SkTArray<SkOpContour> contours;
    SkOpEdgeBuilder builder(path, contours);
    builder.finish();
    int count = contours.count();
    int outer;
    SkTArray<int, true> runs(count);  // indices of partial contours
    for (outer = 0; outer < count; ++outer) {
        const SkOpContour& eContour = contours[outer];
        const SkPoint& eStart = eContour.start();
        const SkPoint& eEnd = eContour.end();
#if DEBUG_ASSEMBLE
        SkDebugf("%s contour", __FUNCTION__);
        if (!SkDPoint::ApproximatelyEqual(eStart, eEnd)) {
            SkDebugf("[%d]", runs.count());
        } else {
            SkDebugf("   ");
        }
        SkDebugf(" start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n",
                eStart.fX, eStart.fY, eEnd.fX, eEnd.fY);
#endif
        if (SkDPoint::ApproximatelyEqual(eStart, eEnd)) {
            eContour.toPath(simple);
            continue;
        }
        runs.push_back(outer);
    }
    count = runs.count();
    if (count == 0) {
        return;
    }
    SkTArray<int, true> sLink, eLink;
    sLink.push_back_n(count);
    eLink.push_back_n(count);
    int rIndex, iIndex;
    for (rIndex = 0; rIndex < count; ++rIndex) {
        sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
    }
    const int ends = count * 2;  // all starts and ends
    const int entries = (ends - 1) * count;  // folded triangle : n * (n - 1) / 2
    SkTArray<double, true> distances;
    distances.push_back_n(entries);
    for (rIndex = 0; rIndex < ends - 1; ++rIndex) {
        outer = runs[rIndex >> 1];
        const SkOpContour& oContour = contours[outer];
        const SkPoint& oPt = rIndex & 1 ? oContour.end() : oContour.start();
        const int row = rIndex < count - 1 ? rIndex * ends : (ends - rIndex - 2)
                * ends - rIndex - 1;
        for (iIndex = rIndex + 1; iIndex < ends; ++iIndex) {
            int inner = runs[iIndex >> 1];
            const SkOpContour& iContour = contours[inner];
            const SkPoint& iPt = iIndex & 1 ? iContour.end() : iContour.start();
            double dx = iPt.fX - oPt.fX;
            double dy = iPt.fY - oPt.fY;
            double dist = dx * dx + dy * dy;
            distances[row + iIndex] = dist;  // oStart distance from iStart
        }
    }
    SkTArray<int, true> sortedDist;
    sortedDist.push_back_n(entries);
    for (rIndex = 0; rIndex < entries; ++rIndex) {
        sortedDist[rIndex] = rIndex;
    }
    SkTQSort<int>(sortedDist.begin(), sortedDist.end() - 1, DistanceLessThan(distances.begin()));
    int remaining = count;  // number of start/end pairs
    for (rIndex = 0; rIndex < entries; ++rIndex) {
        int pair = sortedDist[rIndex];
        int row = pair / ends;
        int col = pair - row * ends;
        int thingOne = row < col ? row : ends - row - 2;
        int ndxOne = thingOne >> 1;
        bool endOne = thingOne & 1;
        int* linkOne = endOne ? eLink.begin() : sLink.begin();
        if (linkOne[ndxOne] != SK_MaxS32) {
            continue;
        }
        int thingTwo = row < col ? col : ends - row + col - 1;
        int ndxTwo = thingTwo >> 1;
        bool endTwo = thingTwo & 1;
        int* linkTwo = endTwo ? eLink.begin() : sLink.begin();
        if (linkTwo[ndxTwo] != SK_MaxS32) {
            continue;
        }
        SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
        bool flip = endOne == endTwo;
        linkOne[ndxOne] = flip ? ~ndxTwo : ndxTwo;
        linkTwo[ndxTwo] = flip ? ~ndxOne : ndxOne;
        if (!--remaining) {
            break;
        }
    }
    SkASSERT(!remaining);
#if DEBUG_ASSEMBLE
    for (rIndex = 0; rIndex < count; ++rIndex) {
        int s = sLink[rIndex];
        int e = eLink[rIndex];
        SkDebugf("%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__, s < 0 ? 's' : 'e',
                s < 0 ? ~s : s, rIndex, rIndex, e < 0 ? 'e' : 's', e < 0 ? ~e : e);
    }
#endif
    rIndex = 0;
    do {
        bool forward = true;
        bool first = true;
        int sIndex = sLink[rIndex];
        SkASSERT(sIndex != SK_MaxS32);
        sLink[rIndex] = SK_MaxS32;
        int eIndex;
        if (sIndex < 0) {
            eIndex = sLink[~sIndex];
            sLink[~sIndex] = SK_MaxS32;
        } else {
            eIndex = eLink[sIndex];
            eLink[sIndex] = SK_MaxS32;
        }
        SkASSERT(eIndex != SK_MaxS32);
#if DEBUG_ASSEMBLE
        SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
                    sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
                    eIndex < 0 ? ~eIndex : eIndex);
#endif
        do {
            outer = runs[rIndex];
            const SkOpContour& contour = contours[outer];
            if (first) {
                first = false;
                const SkPoint* startPtr = &contour.start();
                simple->deferredMove(startPtr[0]);
            }
            if (forward) {
                contour.toPartialForward(simple);
            } else {
                contour.toPartialBackward(simple);
            }
#if DEBUG_ASSEMBLE
            SkDebugf("%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex,
                eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex,
                sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
#endif
            if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
                simple->close();
                break;
            }
            if (forward) {
                eIndex = eLink[rIndex];
                SkASSERT(eIndex != SK_MaxS32);
                eLink[rIndex] = SK_MaxS32;
                if (eIndex >= 0) {
                    SkASSERT(sLink[eIndex] == rIndex);
                    sLink[eIndex] = SK_MaxS32;
                } else {
                    SkASSERT(eLink[~eIndex] == ~rIndex);
                    eLink[~eIndex] = SK_MaxS32;
                }
            } else {
                eIndex = sLink[rIndex];
                SkASSERT(eIndex != SK_MaxS32);
                sLink[rIndex] = SK_MaxS32;
                if (eIndex >= 0) {
                    SkASSERT(eLink[eIndex] == rIndex);
                    eLink[eIndex] = SK_MaxS32;
                } else {
                    SkASSERT(sLink[~eIndex] == ~rIndex);
                    sLink[~eIndex] = SK_MaxS32;
                }
            }
            rIndex = eIndex;
            if (rIndex < 0) {
                forward ^= 1;
                rIndex = ~rIndex;
            }
        } while (true);
        for (rIndex = 0; rIndex < count; ++rIndex) {
            if (sLink[rIndex] != SK_MaxS32) {
                break;
            }
        }
    } while (rIndex < count);
#if DEBUG_ASSEMBLE
    for (rIndex = 0; rIndex < count; ++rIndex) {
       SkASSERT(sLink[rIndex] == SK_MaxS32);
       SkASSERT(eLink[rIndex] == SK_MaxS32);
    }
#endif
}
Esempio n. 7
0
// Create the base Vulkan objects needed by the GrVkGpu object
const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
                             bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex)) {
    VkPhysicalDevice physDev;
    VkDevice device;
    VkInstance inst;
    VkResult err;

    const VkApplicationInfo app_info = {
        VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
        nullptr,                            // pNext
        "vktest",                           // pApplicationName
        0,                                  // applicationVersion
        "vktest",                           // pEngineName
        0,                                  // engineVerison
        kGrVkMinimumVersion,                // apiVersion
    };

    GrVkExtensions extensions;
    extensions.initInstance(kGrVkMinimumVersion);

    SkTArray<const char*> instanceLayerNames;
    SkTArray<const char*> instanceExtensionNames;
    uint32_t extensionFlags = 0;
#ifdef ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
            instanceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
    if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
        extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
    }
#endif

    if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_surface_GrVkExtensionFlag;
    }
    if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
#ifdef SK_BUILD_FOR_WIN
    if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
    }
#elif SK_BUILD_FOR_ANDROID
    if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
}
#elif SK_BUILD_FOR_UNIX
    if (extensions.hasInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) {
        instanceExtensionNames.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
        extensionFlags |= kKHR_xlib_surface_GrVkExtensionFlag;
    }
#endif

    const VkInstanceCreateInfo instance_create = {
        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,    // sType
        nullptr,                                   // pNext
        0,                                         // flags
        &app_info,                                 // pApplicationInfo
        (uint32_t) instanceLayerNames.count(),     // enabledLayerNameCount
        instanceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
        instanceExtensionNames.begin(),            // ppEnabledExtensionNames
    };

    err = vkCreateInstance(&instance_create, nullptr, &inst);
    if (err < 0) {
        SkDebugf("vkCreateInstance failed: %d\n", err);
        return nullptr;
    }

    uint32_t gpuCount;
    err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
    if (err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        vkDestroyInstance(inst, nullptr);
        return nullptr;
    }
    SkASSERT(gpuCount > 0);
    // Just returning the first physical device instead of getting the whole array.
    // TODO: find best match for our needs
    gpuCount = 1;
    err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
    if (err) {
        SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
        vkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    // query to get the initial queue props size
    uint32_t queueCount;
    vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
    SkASSERT(queueCount >= 1);

    SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
    // now get the actual queue props
    VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();

    vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);

    // iterate to find the graphics queue
    uint32_t graphicsQueueIndex = queueCount;
    for (uint32_t i = 0; i < queueCount; i++) {
        if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            graphicsQueueIndex = i;
            break;
        }
    }
    SkASSERT(graphicsQueueIndex < queueCount);

    // iterate to find the present queue, if needed
    uint32_t presentQueueIndex = graphicsQueueIndex;
    if (presentQueueIndexPtr && canPresent) {
        for (uint32_t i = 0; i < queueCount; i++) {
            if (canPresent(inst, physDev, i)) {
                presentQueueIndex = i;
                break;
            }
        }
        SkASSERT(presentQueueIndex < queueCount);
        *presentQueueIndexPtr = presentQueueIndex;
    }

    extensions.initDevice(kGrVkMinimumVersion, inst, physDev);

    SkTArray<const char*> deviceLayerNames;
    SkTArray<const char*> deviceExtensionNames;
#ifdef ENABLE_VK_LAYERS
    for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
        if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
            deviceLayerNames.push_back(kDebugLayerNames[i]);
        }
    }
#endif
    if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
        deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
        extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
    }
    if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
        deviceExtensionNames.push_back("VK_NV_glsl_shader");
        extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
    }

    // query to get the physical device properties
    VkPhysicalDeviceFeatures deviceFeatures;
    vkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
    // this looks like it would slow things down,
    // and we can't depend on it on all platforms
    deviceFeatures.robustBufferAccess = VK_FALSE;

    uint32_t featureFlags = 0;
    if (deviceFeatures.geometryShader) {
        featureFlags |= kGeometryShader_GrVkFeatureFlag;
    }
    if (deviceFeatures.dualSrcBlend) {
        featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
    }
    if (deviceFeatures.sampleRateShading) {
        featureFlags |= kSampleRateShading_GrVkFeatureFlag;
    }

    float queuePriorities[1] = { 0.0 };
    // Here we assume no need for swapchain queue
    // If one is needed, the client will need its own setup code
    const VkDeviceQueueCreateInfo queueInfo[2] = {
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            graphicsQueueIndex,                         // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        },
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            nullptr,                                    // pNext
            0,                                          // VkDeviceQueueCreateFlags
            presentQueueIndex,                          // queueFamilyIndex
            1,                                          // queueCount
            queuePriorities,                            // pQueuePriorities
        }
    };
    uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;

    const VkDeviceCreateInfo deviceInfo = {
        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,    // sType
        nullptr,                                 // pNext
        0,                                       // VkDeviceCreateFlags
        queueInfoCount,                          // queueCreateInfoCount
        queueInfo,                               // pQueueCreateInfos
        (uint32_t) deviceLayerNames.count(),     // layerCount
        deviceLayerNames.begin(),                // ppEnabledLayerNames
        (uint32_t) deviceExtensionNames.count(), // extensionCount
        deviceExtensionNames.begin(),            // ppEnabledExtensionNames
        &deviceFeatures                          // ppEnabledFeatures
    };

    err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device);
    if (err) {
        SkDebugf("CreateDevice failed: %d\n", err);
        vkDestroyInstance(inst, nullptr);
        return nullptr;
    }

    VkQueue queue;
    vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);

    GrVkBackendContext* ctx = new GrVkBackendContext();
    ctx->fInstance = inst;
    ctx->fPhysicalDevice = physDev;
    ctx->fDevice = device;
    ctx->fQueue = queue;
    ctx->fGraphicsQueueIndex = graphicsQueueIndex;
    ctx->fMinAPIVersion = kGrVkMinimumVersion;
    ctx->fExtensions = extensionFlags;
    ctx->fFeatures = featureFlags;
    ctx->fInterface.reset(GrVkCreateInterface(inst, device, extensionFlags));

    return ctx;
}
Esempio n. 8
0
void GLCpuPosInstancedArraysBench::teardown(const GrGLInterface* gl) {
    GR_GL_CALL(gl, DeleteProgram(fProgram));
    GR_GL_CALL(gl, DeleteBuffers(fBuffers.count(), fBuffers.begin()));
    GR_GL_CALL(gl, DeleteVertexArrays(1, &fVAO));
}
void GrDistanceFieldTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
                                               const GrPaint& paint,
                                               const SkPaint& skPaint, const SkMatrix& viewMatrix,
                                               const char text[], size_t byteLength,
                                               const SkScalar pos[], int scalarsPerPosition,
                                               const SkPoint& offset,
                                               const SkIRect& regionClipBounds) {

    SkASSERT(byteLength == 0 || text != NULL);
    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);

    // nothing to draw
    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
        return;
    }

    fViewMatrix = viewMatrix;
    this->init(rt, clip, paint, skPaint, regionClipBounds);

    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();

    SkAutoGlyphCacheNoGamma    autoCache(fSkPaint, &fDeviceProperties, NULL);
    SkGlyphCache*              cache = autoCache.getCache();
    GrFontScaler*              fontScaler = GetGrFontScaler(cache);

    int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
    fTotalVertexCount = kVerticesPerGlyph*numGlyphs;

    const char*        stop = text + byteLength;
    SkTArray<char>     fallbackTxt;
    SkTArray<SkScalar> fallbackPos;

    if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
        while (text < stop) {
            const char* lastText = text;
            // the last 2 parameters are ignored
            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);

            if (glyph.fWidth) {
                SkScalar x = offset.x() + pos[0];
                SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);

                if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                                     glyph.getSubXFixed(),
                                                     glyph.getSubYFixed(),
                                                     GrGlyph::kDistance_MaskStyle),
                                       x, y, fontScaler)) {
                    // couldn't append, send to fallback
                    fallbackTxt.push_back_n(SkToInt(text-lastText), lastText);
                    fallbackPos.push_back(pos[0]);
                    if (2 == scalarsPerPosition) {
                        fallbackPos.push_back(pos[1]);
                    }
                }
            }
            pos += scalarsPerPosition;
        }
    } else {
        SkScalar alignMul = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? SK_ScalarHalf
                                                                              : SK_Scalar1;
        while (text < stop) {
            const char* lastText = text;
            // the last 2 parameters are ignored
            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);

            if (glyph.fWidth) {
                SkScalar x = offset.x() + pos[0];
                SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);

                SkScalar advanceX = SkFixedToScalar(glyph.fAdvanceX)*alignMul*fTextRatio;
                SkScalar advanceY = SkFixedToScalar(glyph.fAdvanceY)*alignMul*fTextRatio;

                if (!this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                                     glyph.getSubXFixed(),
                                                     glyph.getSubYFixed(),
                                                     GrGlyph::kDistance_MaskStyle),
                                       x - advanceX, y - advanceY, fontScaler)) {
                    // couldn't append, send to fallback
                    fallbackTxt.push_back_n(SkToInt(text-lastText), lastText);
                    fallbackPos.push_back(pos[0]);
                    if (2 == scalarsPerPosition) {
                        fallbackPos.push_back(pos[1]);
                    }
                }
            }
            pos += scalarsPerPosition;
        }
    }

    this->finish();
    
    if (fallbackTxt.count() > 0) {
        fFallbackTextContext->drawPosText(rt, clip, paint, skPaint, viewMatrix,
                                          fallbackTxt.begin(), fallbackTxt.count(),
                                          fallbackPos.begin(), scalarsPerPosition, offset,
                                          regionClipBounds);
    }
}
void GrDistanceFieldTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
                                            const GrPaint& paint,
                                            const SkPaint& skPaint, const SkMatrix& viewMatrix,
                                            const char text[], size_t byteLength,
                                            SkScalar x, SkScalar y,
                                            const SkIRect& regionClipBounds) {
    SkASSERT(byteLength == 0 || text != NULL);

    // nothing to draw
    if (text == NULL || byteLength == 0) {
        return;
    }

    fViewMatrix = viewMatrix;
    SkDrawCacheProc          glyphCacheProc = skPaint.getDrawCacheProc();
    SkAutoGlyphCache         autoCache(skPaint, &fDeviceProperties, NULL);
    SkGlyphCache*            cache = autoCache.getCache();

    SkTArray<SkScalar> positions;

    const char* textPtr = text;
    SkFixed stopX = 0;
    SkFixed stopY = 0;
    SkFixed origin;
    switch (skPaint.getTextAlign()) {
        case SkPaint::kRight_Align: origin = SK_Fixed1; break;
        case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
        case SkPaint::kLeft_Align: origin = 0; break;
        default: SkFAIL("Invalid paint origin"); return;
    }

    SkAutoKern autokern;
    const char* stop = text + byteLength;
    while (textPtr < stop) {
        // don't need x, y here, since all subpixel variants will have the
        // same advance
        const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);

        SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
        positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));

        SkFixed height = glyph.fAdvanceY;
        positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));

        stopX += width;
        stopY += height;
    }
    SkASSERT(textPtr == stop);

    // now adjust starting point depending on alignment
    SkScalar alignX = SkFixedToScalar(stopX);
    SkScalar alignY = SkFixedToScalar(stopY);
    if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
        alignX = SkScalarHalf(alignX);
        alignY = SkScalarHalf(alignY);
    } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
        alignX = 0;
        alignY = 0;
    }
    x -= alignX;
    y -= alignY;
    SkPoint offset = SkPoint::Make(x, y);

    this->onDrawPosText(rt, clip, paint, skPaint, viewMatrix, text, byteLength, positions.begin(),
                        2, offset, regionClipBounds);
}
Esempio n. 11
0
void GrTextUtils::DrawDFText(GrAtlasTextBlob* blob, int runIndex,
                             GrBatchFontCache* fontCache, const SkSurfaceProps& props,
                             const SkPaint& skPaint, GrColor color,
                             const SkMatrix& viewMatrix,
                             const char text[], size_t byteLength,
                             SkScalar x, SkScalar y) {
    SkASSERT(byteLength == 0 || text != nullptr);

    // nothing to draw
    if (text == nullptr || byteLength == 0) {
        return;
    }

    SkPaint::GlyphCacheProc glyphCacheProc = skPaint.getGlyphCacheProc(true);
    SkAutoDescriptor desc;
    skPaint.getScalerContextDescriptor(&desc, props, SkPaint::FakeGamma::Off, nullptr);
    SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(skPaint.getTypeface(),
                                                             desc.getDesc());

    SkTArray<SkScalar> positions;

    const char* textPtr = text;
    SkFixed stopX = 0;
    SkFixed stopY = 0;
    SkFixed origin = 0;
    switch (skPaint.getTextAlign()) {
        case SkPaint::kRight_Align: origin = SK_Fixed1; break;
        case SkPaint::kCenter_Align: origin = SK_FixedHalf; break;
        case SkPaint::kLeft_Align: origin = 0; break;
    }

    SkAutoKern autokern;
    const char* stop = text + byteLength;
    while (textPtr < stop) {
        // don't need x, y here, since all subpixel variants will have the
        // same advance
        const SkGlyph& glyph = glyphCacheProc(origPaintCache, &textPtr);

        SkFixed width = glyph.fAdvanceX + autokern.adjust(glyph);
        positions.push_back(SkFixedToScalar(stopX + SkFixedMul(origin, width)));

        SkFixed height = glyph.fAdvanceY;
        positions.push_back(SkFixedToScalar(stopY + SkFixedMul(origin, height)));

        stopX += width;
        stopY += height;
    }
    SkASSERT(textPtr == stop);

    SkGlyphCache::AttachCache(origPaintCache);

    // now adjust starting point depending on alignment
    SkScalar alignX = SkFixedToScalar(stopX);
    SkScalar alignY = SkFixedToScalar(stopY);
    if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
        alignX = SkScalarHalf(alignX);
        alignY = SkScalarHalf(alignY);
    } else if (skPaint.getTextAlign() == SkPaint::kLeft_Align) {
        alignX = 0;
        alignY = 0;
    }
    x -= alignX;
    y -= alignY;
    SkPoint offset = SkPoint::Make(x, y);

    DrawDFPosText(blob, runIndex, fontCache, props, skPaint, color, viewMatrix, text, byteLength,
                  positions.begin(), 2, offset);
}
Esempio n. 12
0
bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
#if DEBUG_SHOW_TEST_NAME
    char* debugName = DEBUG_FILENAME_STRING;
    if (debugName && debugName[0]) {
        SkPathOpsDebug::BumpTestName(debugName);
        SkPathOpsDebug::ShowPath(one, two, op, debugName);
    }
#endif
    op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()];
    SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isInverseFillType()]
            ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType;
    const SkPath* minuend = &one;
    const SkPath* subtrahend = &two;
    if (op == kReverseDifference_PathOp) {
        minuend = &two;
        subtrahend = &one;
        op = kDifference_PathOp;
    }
#if DEBUG_SORT || DEBUG_SWAP_TOP
    SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
#endif
    // turn path into list of segments
    SkTArray<SkOpContour> contours;
    // FIXME: add self-intersecting cubics' T values to segment
    SkOpEdgeBuilder builder(*minuend, contours);
    const int xorMask = builder.xorMask();
    builder.addOperand(*subtrahend);
    if (!builder.finish()) {
        return false;
    }
    result->reset();
    result->setFillType(fillType);
    const int xorOpMask = builder.xorMask();
    SkTArray<SkOpContour*, true> contourList;
    MakeContourList(contours, contourList, xorMask == kEvenOdd_PathOpsMask,
            xorOpMask == kEvenOdd_PathOpsMask);
    SkOpContour** currentPtr = contourList.begin();
    if (!currentPtr) {
        return true;
    }
    SkOpContour** listEnd = contourList.end();
    // find all intersections between segments
    do {
        SkOpContour** nextPtr = currentPtr;
        SkOpContour* current = *currentPtr++;
        if (current->containsCubics()) {
            AddSelfIntersectTs(current);
        }
        SkOpContour* next;
        do {
            next = *nextPtr++;
        } while (AddIntersectTs(current, next) && nextPtr != listEnd);
    } while (currentPtr != listEnd);
    // eat through coincident edges

    int total = 0;
    int index;
    for (index = 0; index < contourList.count(); ++index) {
        total += contourList[index]->segments().count();
    }
    HandleCoincidence(&contourList, total);
    // construct closed contours
    SkPathWriter wrapper(*result);
    bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper);
    {  // if some edges could not be resolved, assemble remaining fragments
        SkPath temp;
        temp.setFillType(fillType);
        SkPathWriter assembled(temp);
        Assemble(wrapper, &assembled);
        *result = *assembled.nativePath();
        result->setFillType(fillType);
    }
    return true;
}
Esempio n. 13
0
bool SkKTXFile::WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap) {
    const SkColorType ct = bitmap.colorType();
    SkAutoLockPixels alp(bitmap);

    const int width = bitmap.width();
    const int height = bitmap.width();
    const uint8_t* src = reinterpret_cast<uint8_t*>(bitmap.getPixels());
    if (NULL == bitmap.getPixels()) {
        return false;
    }

    // First thing's first, write out the magic identifier and endianness...
    if (!stream->write(KTX_FILE_IDENTIFIER, KTX_FILE_IDENTIFIER_SIZE) ||
        !stream->write(&kKTX_ENDIANNESS_CODE, 4)) {
        return false;
    }

    // Collect our key/value pairs...
    SkTArray<KeyValue> kvPairs;

    // Next, write the header based on the bitmap's config.
    Header hdr;
    switch (ct) {
        case kIndex_8_SkColorType:
            // There is a compressed format for this, but we don't support it yet.
            SkDebugf("Writing indexed bitmap to KTX unsupported.\n");
            // VVV fall through VVV
        default:
        case kUnknown_SkColorType:
            // Bitmap hasn't been configured.
            return false;

        case kAlpha_8_SkColorType:
            hdr.fGLType = GR_GL_UNSIGNED_BYTE;
            hdr.fGLTypeSize = 1;
            hdr.fGLFormat = GR_GL_RED;
            hdr.fGLInternalFormat = GR_GL_R8;
            hdr.fGLBaseInternalFormat = GR_GL_RED;
            break;

        case kRGB_565_SkColorType:
            hdr.fGLType = GR_GL_UNSIGNED_SHORT_5_6_5;
            hdr.fGLTypeSize = 2;
            hdr.fGLFormat = GR_GL_RGB;
            hdr.fGLInternalFormat = GR_GL_RGB;
            hdr.fGLBaseInternalFormat = GR_GL_RGB;
            break;

        case kARGB_4444_SkColorType:
            hdr.fGLType = GR_GL_UNSIGNED_SHORT_4_4_4_4;
            hdr.fGLTypeSize = 2;
            hdr.fGLFormat = GR_GL_RGBA;
            hdr.fGLInternalFormat = GR_GL_RGBA4;
            hdr.fGLBaseInternalFormat = GR_GL_RGBA;
            kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True"));
            break;

        case kN32_SkColorType:
            hdr.fGLType = GR_GL_UNSIGNED_BYTE;
            hdr.fGLTypeSize = 1;
            hdr.fGLFormat = GR_GL_RGBA;
            hdr.fGLInternalFormat = GR_GL_RGBA8;
            hdr.fGLBaseInternalFormat = GR_GL_RGBA;
            kvPairs.push_back(CreateKeyValue("KTXPremultipliedAlpha", "True"));
            break;
    }

    // Everything else in the header is shared.
    hdr.fPixelWidth = width;
    hdr.fPixelHeight = height;
    hdr.fNumberOfArrayElements = 0;
    hdr.fNumberOfFaces = 1;
    hdr.fNumberOfMipmapLevels = 1;

    // Calculate the key value data size
    hdr.fBytesOfKeyValueData = 0;
    for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) {
        // Key value size is the size of the key value data,
        // four bytes for saying how big the key value size is
        // and then additional bytes for padding to four byte boundary
        size_t kvsize = kv->size();
        kvsize += 4;
        kvsize = (kvsize + 3) & ~3;
        hdr.fBytesOfKeyValueData = SkToU32(hdr.fBytesOfKeyValueData + kvsize);
    }

    // Write the header
    if (!stream->write(&hdr, sizeof(hdr))) {
        return false;
    }

    // Write out each key value pair
    for (KeyValue *kv = kvPairs.begin(); kv != kvPairs.end(); ++kv) {
        if (!kv->writeKeyAndValueForKTX(stream)) {
            return false;
        }
    }

    // Calculate the size of the data
    int bpp = bitmap.bytesPerPixel();
    uint32_t dataSz = bpp * width * height;

    if (0 >= bpp) {
        return false;
    }

    // Write it into the buffer
    if (!stream->write(&dataSz, 4)) {
        return false;
    }

    // Write the pixel data...
    const uint8_t* rowPtr = src;
    if (kN32_SkColorType == ct) {
        for (int j = 0; j < height; ++j) {
            const uint32_t* pixelsPtr = reinterpret_cast<const uint32_t*>(rowPtr);
            for (int i = 0; i < width; ++i) {
                uint32_t pixel = pixelsPtr[i];
                uint8_t dstPixel[4];
                dstPixel[0] = pixel >> SK_R32_SHIFT;
                dstPixel[1] = pixel >> SK_G32_SHIFT;
                dstPixel[2] = pixel >> SK_B32_SHIFT;
                dstPixel[3] = pixel >> SK_A32_SHIFT;
                if (!stream->write(dstPixel, 4)) {
                    return false;
                }
            }
            rowPtr += bitmap.rowBytes();
        }
    } else {
        for (int i = 0; i < height; ++i) {
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
        std::unique_ptr<GrFragmentProcessor>* series, int cnt) {
    class SeriesFragmentProcessor : public GrFragmentProcessor {
    public:
        static std::unique_ptr<GrFragmentProcessor> Make(
                std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
            return std::unique_ptr<GrFragmentProcessor>(new SeriesFragmentProcessor(children, cnt));
        }

        const char* name() const override { return "Series"; }

        std::unique_ptr<GrFragmentProcessor> clone() const override {
            SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> children(this->numChildProcessors());
            for (int i = 0; i < this->numChildProcessors(); ++i) {
                if (!children.push_back(this->childProcessor(i).clone())) {
                    return nullptr;
                }
            }
            return Make(children.begin(), this->numChildProcessors());
        }

    private:
        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
            class GLFP : public GrGLSLFragmentProcessor {
            public:
                void emitCode(EmitArgs& args) override {
                    // First guy's input might be nil.
                    SkString temp("out0");
                    this->emitChild(0, args.fInputColor, &temp, args);
                    SkString input = temp;
                    for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
                        temp.printf("out%d", i);
                        this->emitChild(i, input.c_str(), &temp, args);
                        input = temp;
                    }
                    // Last guy writes to our output variable.
                    this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
                }
            };
            return new GLFP;
        }

        SeriesFragmentProcessor(std::unique_ptr<GrFragmentProcessor>* children, int cnt)
                : INHERITED(kSeriesFragmentProcessor_ClassID, OptFlags(children, cnt)) {
            SkASSERT(cnt > 1);
            for (int i = 0; i < cnt; ++i) {
                this->registerChildProcessor(std::move(children[i]));
            }
        }

        static OptimizationFlags OptFlags(std::unique_ptr<GrFragmentProcessor>* children, int cnt) {
            OptimizationFlags flags = kAll_OptimizationFlags;
            for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
                flags &= children[i]->optimizationFlags();
            }
            return flags;
        }
        void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}

        bool onIsEqual(const GrFragmentProcessor&) const override { return true; }

        GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
            int childCnt = this->numChildProcessors();
            for (int i = 0; i < childCnt; ++i) {
                color = ConstantOutputForConstantInput(this->childProcessor(i), color);
            }
            return color;
        }

        typedef GrFragmentProcessor INHERITED;
    };

    if (!cnt) {
        return nullptr;
    }
    if (1 == cnt) {
        return std::move(series[0]);
    }
    // Run the through the series, do the invariant output processing, and look for eliminations.
    GrProcessorAnalysisColor inputColor;
    inputColor.setToUnknown();
    GrColorFragmentProcessorAnalysis info(inputColor, unique_ptr_address_as_pointer_address(series),
                                          cnt);
    SkTArray<std::unique_ptr<GrFragmentProcessor>> replacementSeries;
    GrColor4f knownColor;
    int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
    if (leadingFPsToEliminate) {
        std::unique_ptr<GrFragmentProcessor> colorFP(
                GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::InputMode::kIgnore));
        if (leadingFPsToEliminate == cnt) {
            return colorFP;
        }
        cnt = cnt - leadingFPsToEliminate + 1;
        replacementSeries.reserve(cnt);
        replacementSeries.emplace_back(std::move(colorFP));
        for (int i = 0; i < cnt - 1; ++i) {
            replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
        }
        series = replacementSeries.begin();
    }
    return SeriesFragmentProcessor::Make(series, cnt);
}